如何强制实现受保护的静态函数

use*_*613 3 php static protected abstract

我正在尝试编写一个抽象类(或接口),它强制扩展类实现受保护的静态函数.但这对于抽象类和接口来说既不可能.

错误:

  • 静态函数不应该是抽象的
  • 必须省略接口成员的访问类型

任何想法如何实现?

UPDATE

目的基本上是静态调用公共函数.这样,该类不需要实例化.也没有必要从类外部代码中调用_doSpecificStuff().

abstract class Foo
{
    public static function doStuff()
    {
        [generic code] 

        static::_doSpecificStuff();
    }

    // sth like that would be nice to have:
    abstract static protected function _doSpecificStuff();
}
Run Code Online (Sandbox Code Playgroud)

dec*_*eze 5

从理论和实践的角度来看,没有必要声明静态方法摘要.

有一个子类填充空白的抽象方法.这通常是因为父类(原始抽象类)执行一些通用操作,但可以/必须适应某些特定情况,因此可以强制子类在其他通用算法中仅实现此特定变量部分.抽象方法应该是更大算法中的空白点.

父方法将调用其抽象方法的实现,而无需了解或关心谁实现它们或如何实现它们:

abstract class Foo {

    public function someAlgo() {
        $foo = $this->doSomethingSpecific();
        ...
    }

    abstract protected function doSomethingSpecific();

}
Run Code Online (Sandbox Code Playgroud)

Foo不关心谁或什么填补空白doSomethingSpecific,它只是依赖它在那里和它的签名,abstract强制执行.实现此方法的特定对象或其实现方式是可变的.这很重要,也是问题的核心.

在这种情况下,声明静态方法摘要是没用的.任何静态方法都可以作为非静态方法实现,因此这里没有用处.如果类本身应该将抽象方法作为如上所述的更大的通用算法的一部分来调用,则不需要静态方法.

因此,静态方法的唯一方案是可以public static从任何地方调用的方法:

abstract class Foo {

    abstract public static function bar();

}

class Baz extends Foo {

    public static function bar() { ... }

}

Baz::bar();
Run Code Online (Sandbox Code Playgroud)

问题是,因为abstract class Foo它本身并不调用这个函数,但是这个函数只是从外部代码调用,你实际上并不是在谈论填空方法,而是在讨论一个接口.所以,你应该使用一个interface代替.
但即便如此,由于您必须在源代码中键入特定的类名,硬编码,因此接口也没有什么意义.

声明接口或抽象方法签名的关键在于您要修复方法签名,以便任何代码都可以调用该特定方法,而无需关心它正在调用它的对象.但是,由于您必须对类名进行硬编码,因此您调用它的对象没有可变性.如果你键入Baz::bar(),你确切地知道你正在调用什么类的方法.因此,抽象接口/签名没什么意义.


相比:

interface FooInterface {

    public function bar();

}

function baz(FooInterface $foo) {
    $foo->bar();
}
Run Code Online (Sandbox Code Playgroud)

由于接口声明,该函数baz可以依赖于具有bar()方法的参数.实现该方法的具体对象是无关紧要的,并且会有所不同.

abstract class Foo {

    public function someAlgo() {
        $foo = $this->doSomethingSpecific();
        ...
    }

    abstract protected function doSomethingSpecific();

}
Run Code Online (Sandbox Code Playgroud)

该类Foo可以依赖它具有该doSomethingSpecific方法.实现该方法的具体对象是无关紧要的,并且会有所不同.

abstract class Foo {

    abstract public static function bar();

}

class Baz extends Foo {

    public static function bar() { ... }

}

Baz::bar();
Run Code Online (Sandbox Code Playgroud)

你究竟在这里依赖或抽象出什么?你可以非常确定每次Baz都会有这个方法bar(),因为你只是在同一个硬编码的类上调用它.这里没有变数.