在定义结构并继承Interface和/或Abstract 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]的样本 - >没有接口的[类]
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);
答案 0 :(得分:9)
抽象类定义了必须对抽象类的继承人实现的接口。 Interface-Construct定义了一个必须由实现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');
}
}
答案 1 :(得分:2)
真正抽象的类和接口是不同的。
将接口视为契约,它规定了其他类(实现它)必须遵循的规则。
另一方面,抽象类更像是起点,其他类可以构建,因此它们有时被称为基类。
-------用示例编辑
我不是这方面的专家,但我一直都在做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();
}
}
我经常有一个基类,其他人扩展,但我只在真实世界的应用程序中使用了一个抽象类,最终被替换。
我确信有更好的方法可以做,但过去这对我来说非常有效。
答案 2 :(得分:0)
我的声誉不允许发表评论,但tr0y的答案中的这句话具有误导性:
“抽象类定义了一个必须对抽象类的继承人实现的接口。”
接口和抽象类之间的主要区别之一是,在扩展的类中实现任何抽象类方法所需的 它。抽象类通常具有默认行为的方法,并且如果默认行为不是您想要的,则仅在继承人中提供这些方法。
另一方面, 要求在任何实现该接口的类中创建所有方法。
另一个区别是接口中的方法不能有主体,而抽象类中的方法必须有主体。