是否可以在PHP接口中创建可选方法


Is it possible to create optional methods in a PHP interface?

我正在用PHP做一个项目。我有几个类需要实现一个接口。有些类不需要实现接口中定义的所有方法。是否可以只以更清洁的方式实施其中的一些方法。

接口指定必须由实现它的类实现的方法,您不能跳过一些,尽管您可以创建其他方法。。。。。您可以做的是将您的接口分解为几个"较小"的接口,并根据需要拥有实现一个或多个的类,如PHP Docs

中的示例#3所示

通常,接口定义类必须实现的方法。因此,根据定义,强制实现不想实现的方法会使接口的概念无效。

我看到两种情况:

1.分离接口

通过使用多个较小的接口来组合类接口可以给你很大的控制权,但可能会导致到处都是非常小的接口。

示例

考虑一个可能具有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) { //...

2.抽象类作为默认提供程序

第二种方法是接口和抽象类的组合,它允许您拥有一个通用接口和一些不需要到处实现的方法。

示例

对于上面的同一个示例,这种方法将为您提供一个接口、一个抽象类,然后提供两者的具体实现。在本例中,我还将默认值设置为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时,您可能不再依赖它的接口,因为它可能已经实现了接口,也可能没有实现接口。因此,无论是否有实际的实现,您都必须检查抽象类为其提供默认值的所有方法。(旁注:否则你必须检查接口,所以无论如何你都必须检查一些东西。)抛开这些缺点不谈(事实上,这并不是真正的实现方式),还有一个好处,那就是你将有一个包含所有方法定义的接口,然后是一个提供一些默认值的抽象类。易于理解-在某些情况下可能比许多界面更容易。(旁注:在第二种情况下,你甚至可以完全删除接口,只要抽象类中没有不能声明的东西。)

接口用于一组类必须执行相同结构的情况。然后实现一个接口来强制实现某些属性或方法。

如果有一些类,就不需要有一些接口方法,所以这个类不应该实现接口。

如果你必须打破规则来实现某个东西,你需要分析你的实现。