【发布时间】:2016-02-26 18:23:01
【问题描述】:
我正在开发一个 PHP 项目。我有几个需要实现接口的类。有些类不需要实现接口中定义的所有方法。是否可以只以更清洁的方式实现某些方法。
【问题讨论】:
我正在开发一个 PHP 项目。我有几个需要实现接口的类。有些类不需要实现接口中定义的所有方法。是否可以只以更清洁的方式实现某些方法。
【问题讨论】:
接口指定了实现它的类必须实现的方法,你不能跳过一些,尽管你可以创建额外的...... . 你可以做的就是将你的接口分成几个“更小的”接口,并根据需要让类实现其中的一个或更多,如示例 #3 中的PHP Docs
【讨论】:
一般来说,接口定义了您的类必须实现的方法。所以根据定义,强制实现你不想实现的方法会使接口的概念无效。
我看到两种情况:
使用多个较小的接口来组合您的类接口可为您提供很多控制权,但可能会导致整个地方的接口都非常小。
考虑一个可能具有 json 正文或某些表单参数的请求类。您的请求可能不会同时具有这两者,但您仍然希望提供接口来共享通用类布局。使用拆分接口,您可以拥有
<?php
interface Request {
public function getHeaders(): array;
}
<?php
interface JsonRequest extends Request {
public function getJsonBody(): string;
}
<?php
interface FormRequest extends Request {
public function getFormParameters(): array;
}
然后用它来指定你的请求类接口:
<?php
class MyRequest implements JsonRequest {
public function getHeaders(): array
{
return ['some' => 'headers'];
}
public function getJsonBody(): string
{
return json_encode(['some' => 'content']);
}
}
这种方法为您提供了清晰且富有表现力的接口以及只需要实现所需内容的类。为了查看请求是否具有 json 正文,您可以检查接口:
if ($request instanceof JsonRequest) { //...
第二种方法可以让您拥有一个通用接口和一些您不需要在任何地方实现的方法,它是接口和抽象类的组合。
对于与上述相同的示例,这种方法将为您提供一个接口、一个抽象类,然后是两者的具体实现。在示例中,我还将默认设置为 null,以便稍后可以对方法内容进行适当的检查。
界面:
<?php
interface RequestInterface {
public function getHeaders(): array;
public function getJsonBody(): ?string;
public function getFormParameters(): ?array;
}
使实现可选的抽象类:
<?php
abstract class AbstractRequest implements RequestInterface {
public function getJsonBody(): ?string
{
return null;
}
public function getFormParameters(): ?array
{
return null;
}
}
然后是实际的请求,这又是一个 json 请求。
<?php
class MyRequest extends AbstractRequest {
public function getHeaders(): array
{
return ['some' => 'headers'];
}
public function getJsonBody(): string
{
return json_encode(['some' => 'content']);
}
}
为了查看请求是否具有 json 正文或某些表单参数,您可以在此示例中检查 null:
if ($request->getJsonBody() !== null) {...
这两种方式在技术上都是有效的(意味着两者都可以工作,但并非都是好的代码),并且可以使用可选方法导致相同的类布局。这两种技术都有优点和缺点。
使用拆分接口提供隐式类型安全性,并更容易依赖接口(也用于其他下游决策,例如如何通过接口实现解析器或处理器,如何处理依赖注入等)。该方法更简洁,并产生更好的代码。但这也可能导致许多具有不同专业的相似类具有许多接口。考虑为请求方法、一些其他选项、可能是一些编码等提供接口。如果您想(!),您最终会得到许多接口和很少的疏忽。
使用抽象类来提供默认实现是在绕开接口的想法,可能会削弱您的代码可用性。每当您在应用程序的某个地方找到一些AbstractRequest 时,您可能不再依赖它的接口,因为它可能已经实现也可能没有实现它们。因此,无论是否存在实际实现,您都必须检查抽象类为其提供默认值的所有方法。 (旁注:否则你必须检查接口,所以无论如何你都必须检查一些东西)把这些缺点放在一边(事实上这并不是事情的实现方式)有好处,您将拥有一个包含所有方法定义的接口,然后是一个提供一些默认值的抽象类。易于理解 - 在某些情况下可能比许多接口更容易。 (旁注:也许你甚至可以在第二种情况下完全放弃接口,只要抽象类中没有不能声明的东西。)
【讨论】:
接口用于一组类必须执行相同结构的情况。比你实现一个接口来强制实现一些属性或方法。
如果有类,则不需要有接口方法,所以这个类不应该实现接口。
如果你必须打破规则来实施某事,你需要分析你的实施。
【讨论】: