繁体   English   中英

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

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

在定义结构并继承Interface和/或Abstract 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());

这里是没有接口的[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());

我目前正在创建一个小应用程序(可能会变得更大)并且对如何在开始时正确实现感到困惑。

顺便说一句,__construct()的这个声明是否在Interface中有意义?

public function __construct($connection);

抽象类定义了必须为抽象类的继承人实现的接口。 Interface-Construct定义了一个必须由实现接口构造的类实现的接口,接口的实现不仅限于单个接口,而类继承耦合到单个(抽象)类。

PHP中的接口有意用于允许整个类接口的有限子集的类型提示。 没有理由在抽象类上使用接口,因为他们的继承者实例的接收者没有使用它们(在instanceof / is_a上使用typehinting或逻辑标识)。 接口构造的更有价值的好处是可以用替代实现替换接口的通用实现。

在你的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');
    }
}

真正抽象的类和接口是不同的。

将接口视为契约,它规定了其他类(实现它)必须遵循的规则。

另一方面,抽象类更像是起点,其他类可以构建,因此它们有时被称为基类。

-------用例子编辑

我不是这方面的专家,但我总是做完interface - > class

例如,这是一个简单的界面:

interface AnimalInterface {

  public function all();

  public function findBySlug($slug);

}

这是实现该接口的类(简化):

class AnimalEloquentRepository implements AnimalInterface {

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

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

}

我经常有一个基类,其他人扩展,但我只在一个真实世界的应用程序中使用了一个抽象类,并最终被取代。

我确信有更好的方法可以做,但这对我来说非常有用。

我的声誉不允许发表评论,但tr0y的回答中的这句话具有误导性:

“抽象类定义了一个必须对抽象类的继承人实现的接口。”

其中的一个接口和抽象类之间的主要区别是,你是不是要实现继承它的类中的任何一个抽象类的方法所需。 如果默认行为不是您想要的,那么抽象类具有默认行为的方法并且仅在继承者中提供这些方法是很常见的。

在另一方面, 需要创造一个实现该接口的类的接口指定的所有方法。

另一个区别是接口中的方法不能有主体,而抽象类中的方法必须有主体。

暂无
暂无

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

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