简体   繁体   English

PHP接口和抽象类继承的最佳实践?

[英]PHP Interface and Abstract Class best practice for inheritance?

When defining the structure and inheriting Interface and/or Abstract Class, which one is the best practice? 在定义结构并继承Interface和/或Abstract Class时,哪一个是最佳实践? And why? 为什么? Here are 2 examples: 这里有两个例子:

Here is the example for [Interface] -> [Abstract Class] -> [Class] 以下是[Interface] - > [Abstract Class] - > [Class]的示例

Interface DataInterface
{
    public function __construct($connection);
    public function connected();
    public function get();
}

Abstract class BaseData implements DataInterface
{
    protected $connection;

    public function __construct($connection)
    {
        $this->connection = $connection;
    }
}


class UserData extends BaseData
{
    public function exists()
    {
        return is_connected($this->connection);
    }

    public function get()
    {
        return get_data($this->connection);
    }
}

$oUserData = new UserData(new Connection());

And here is the sample for [Abstract Class] -> [Class] without the Interface 这里是没有接口的[Abstract Class] - > [Class]的示例

Abstract class BaseData
{
    protected $connection;

    public function __construct($connection)
    {
        $this->connection = $connection;
    }

    abstract public function connected();
    abstract public function get();
}

class UserData extends BaseData
{
    public function exists()
    {
        return is_connected($this->connection);
    }

    public function get()
    {
        return get_data($this->connection);
    }
}

$oUserData = new UserData(new Connection());

I am currently creating a small app (might grow larger) and confused on how to implement in the beginning correctly. 我目前正在创建一个小应用程序(可能会变得更大)并且对如何在开始时正确实现感到困惑。

By the way, is this declaration for __construct() with parameter make sense in Interface? 顺便说一句,__construct()的这个声明是否在Interface中有意义?

public function __construct($connection);

Abstract classes defines an interface that must be implemented to the heirs of the abstract class. 抽象类定义了必须为抽象类的继承人实现的接口。 An Interface-Construct defines an interface that must be implemented by a class that implements the interface-construct, the implementation of the interface is not limited to a single interface, whereas class inheritance is coupled to a single (abstract) class. Interface-Construct定义了一个必须由实现接口构造的类实现的接口,接口的实现不仅限于单个接口,而类继承耦合到单个(抽象)类。

Interfaces in PHP are intentionally used to allow typehints of an limited subset of an entire class interface. PHP中的接口有意用于允许整个类接口的有限子集的类型提示。 There is no reason for an interface on abstract classes aslong their receiver of instances of their heirs did not use them ( with typehinting or logical identification over instanceof / is_a ). 没有理由在抽象类上使用接口,因为他们的继承者实例的接收者没有使用它们(在instanceof / is_a上使用typehinting或逻辑标识)。 The more valuable benefit of interface-constructs are the possibility of replacing an common implementation of an interfaces with a alternate implementation. 接口构造的更有价值的好处是可以用替代实现替换接口的通用实现。

In case of your BaseData-Example, i recommend to drop the abstract idea and use a trait and seperate interfaces instead. 在你的BaseData-Example的情况下,我建议删除抽象的想法,并使用特征和单独的接口。

trait connectionBrokerConstructor {
    protected $connection;

    public function isConnected()
    {
        return $this->connection instanceof Connection;
    }

    public function setConnection(Connection $connection)
    {
        $this->connection = $connection;
    }
}

interface connectable
{
    public function setConnection(Connection $connection);
    public function isConnected();
}

interface userDataRepositoryInterface
{
    public function get();
}

class UserData implements connectable, userDataRepositoryInterface
{
    use connectionBrokerConstructor;

    public function __construct(Connection $connect = null)
    {
        $this->setConnection($connection);
    }

    public function get()
    {
        return array('something');
    }
}

Really abstract classes and interfaces are different. 真正抽象的类和接口是不同的。

Consider an interface as a contract, it lays out the rules that other classes (which implement it) must follow. 将接口视为契约,它规定了其他类(实现它)必须遵循的规则。

Abstract classes on the other hand are more like starting points, which other classes can build on, hence why they are sometimes called base classes. 另一方面,抽象类更像是起点,其他类可以构建,因此它们有时被称为基类。

------- Edit with example -------用例子编辑

I'm not an expert on such things, but I've always just done interface -> class . 我不是这方面的专家,但我总是做完interface - > class

For example, here is a simple interface: 例如,这是一个简单的界面:

interface AnimalInterface {

  public function all();

  public function findBySlug($slug);

}

And here is the class which implements that interface (simplified): 这是实现该接口的类(简化):

class AnimalEloquentRepository implements AnimalInterface {

  public function all()
  {
    return Animal::all();
  }

  public function findBySlug($slug)
  {
    return Animal::whereSlug($slug)->first();
  }

}

I do often have a base class, which others extend, but I've only once used an abstract class in a real world app, and that ended up getting replaced. 我经常有一个基类,其他人扩展,但我只在一个真实世界的应用程序中使用了一个抽象类,并最终被取代。

I'm sure there are better ways to do things, but this has worked really well for me in the past. 我确信有更好的方法可以做,但这对我来说非常有用。

My reputation doesn't allow comments, but this statement in tr0y's answer is misleading: 我的声誉不允许发表评论,但tr0y的回答中的这句话具有误导性:

"Abstract classes defines an interface that must be implemented to the heirs of the abstract class." “抽象类定义了一个必须对抽象类的继承人实现的接口。”

One of the main differences between an interface and an abstract class is that you are not required to implement any of the methods of an abstract class in a class that extends it. 其中的一个接口和抽象类之间的主要区别是,你是不是要实现继承它的类中的任何一个抽象类的方法所需。 It's quite common for the abstract class to have methods with default behavior and only provide those methods in the heirs if the default behavior is not what you want. 如果默认行为不是您想要的,那么抽象类具有默认行为的方法并且仅在继承者中提供这些方法是很常见的。

On the other hand, you are require to create all methods specified in an interface in any class that implements that interface. 在另一方面, 需要创造一个实现该接口的类的接口指定的所有方法。

Another difference is that methods in an interface cannot have a body, while methods in an abstract class must have a body. 另一个区别是接口中的方法不能有主体,而抽象类中的方法必须有主体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM