抽象静态函数并非没有意义!事实上,在我看来,它们使一些设计比我在没有它们的语言(如 Java 或 C#)中不得不求助的更简单、更清晰。
让我们举个例子。假设我正在编写某种普通的企业业务应用程序,它需要在两个 API 之间同步一些业务对象。这些 API 具有可以相互映射的对象模型,但使用不同的名称和不同的序列化格式。
在 PHP 中,多亏了抽象静态方法,我可以为这些业务对象类型定义一个抽象基类,看起来像这样......
abstract class ApiObject {
/** The REST resource URL for this object type in the Foo API. */
abstract static function fooApiResourceUrl();
/** The REST resource URL for this object type in the Bar API. */
abstract static function barApiResourceUrl();
/** Given an XML response from the Foo API representing an object of this
type, construct an instance. */
abstract static function fromFooXml($xml);
/** Given a JSON response from the Bar API representing an object of this
type, construct an instance. */
abstract static function fromBarJson($json);
/** Serialize this object in the XML format that the Foo API understands */
abstract function toFooXml();
/** Serialize this object as JSON that the Bar API understands */
abstract function toBarJson();
}
...然后我创建的每个具体子类都将保证提供从两个 API 中的任何一个获取它并反序列化它所需的所有信息,或者对其进行序列化并将其发送到任一 API。然后,稍后,我可以编写一些这样的代码:
// Ensure that all instances of these types that exist in the Foo API also
// exist in the Bar API:
$classesToSync = ['Widget', 'Frobnicator', 'Lead', 'Invoice'];
foreach ($classesToSync as $apiObjectClass) {
$fooObjXmls = httpGetRequest($apiObjectClass::fooApiResourceUrl());
foreach ($fooObjXmls as $fooObjXml) {
$fooObj = $apiObjectClass::fromFooXml($fooObjXml);
$json = $fooObj->toBarJson();
httpPutRequest($apiObjectClass::barApiResourceUrl(), $json);
}
}
我是否严格需要抽象静态方法来编写上面的程序?不; 我还可以使用其他模式,例如让每个模型类与相应的工厂类配对,该工厂类负责从其 JSON 或 XML 表示中实例化它。但是这样的设计比我上面展示的更复杂。
那么,为什么它们被允许的答案很简单,就是它们很有用,因为它们启用了一些没有它们就不可能实现的漂亮、简单的模式。当然,也存在反对它们的论点,其中一个在问题中给出 - 鉴于抽象类上的静态方法是可调用的,在类上公开抽象静态方法是丑陋的。我不觉得这样的考虑特别有说服力,但即使你这样做了,它们与抽象静态方法提供的实用程序之间仍然存在权衡,PHP 维护人员可能已经权衡了它们并选择了让抽象静态方法的一面存在。