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

Posted

技术标签:

【中文标题】如何强制实现受保护的静态函数【英文标题】:How to force an implementation of a protected static function 【发布时间】:2014-05-15 15:33:48 【问题描述】:

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

错误:

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

有什么想法可以实现吗?

更新

目的基本上是静态调用公共函数。这样类就不需要实例化。 也没有必要使 _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();

【问题讨论】:

【参考方案1】:

从理论和实践的角度来看,没有真正需要声明静态方法抽象。

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

父方法会调用其抽象方法的实现而不知道或关心实现它们或如何实现它们:

abstract class Foo 

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

    abstract protected function doSomethingSpecific();


Foo 不在乎是谁或什么填充了空白doSomethingSpecific,它只依赖于它的存在及其签名,abstract 强制执行。实现此方法或它如何实现它的具体对象是变量。这很重要,也是问题的核心。

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

因此,静态方法剩下的唯一场景是public static 方法,它可以从任何地方调用:

abstract class Foo 

    abstract public static function bar();



class Baz extends Foo 

    public static function bar()  ... 



Baz::bar();

问题是,由于 abstract class Foo 本身并没有调用这个函数,而是这个函数只是从外部代码调用,所以你并不是真的在谈论 fill-in-the-blank方法,你说的是一个接口。因此,您应该改用interface。 但即便如此,由于您必须在源代码中输入特定的类名,硬编码,所以接口也没什么意义。

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


比较:

interface FooInterface 

    public function bar();



function baz(FooInterface $foo) 
    $foo->bar();

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

abstract class Foo 

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

    abstract protected function doSomethingSpecific();


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

abstract class Foo 

    abstract public static function bar();



class Baz extends Foo 

    public static function bar()  ... 



Baz::bar();

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

【讨论】:

感谢您的详细解答!由于 cmets 中的代码格式不起作用,我已经更新了问题。 “这样就不需要实例化类了。” - 这基本上是“面向类的编程”,很大程度上忽略了 OOP。在最近添加了后期静态绑定之前,它根本没有任何意义,甚至现在“面向类的编程”也缺少类的意义。见kunststube.net/static。 你是对的。但是静态方法的想法是独立于实例而行动。当然,解决方案是实例化类。但从程序员的角度来看,没有必要实例化它,因为该方法可以独立于实际实例工作。换句话说:比起范式,我更感兴趣的是可能性。 正如您在我链接到的文章中所读到的,使用静态方法/类是相当有争议的。我可以看到您的用例,但 OOP 应该用于 objects,不鼓励使用对象,这就是您收到 Strict 通知的原因。你仍然可以做你想做的事,但是 php(和我)试图告诉你,也许你一开始就做错了。如果你想忽略它,你必须禁用严格的错误报告。 怎么样:interface FooInterface static function fooMethod(); class A implements FooInterface ... class B implements FooInterface ... 及之后:function callFooMethod($className) if ( is_subclass_of($className, 'FooInterface') ) return $className::fooMethod(); 然后:callFooMethod('A')callFooMethod('B') 虽然我不明白为什么仍然会使用这种方法,但在这种特殊情况下,如何您不会使用界面来确保合规性吗?

以上是关于如何强制实现受保护的静态函数的主要内容,如果未能解决你的问题,请参考以下文章

静态成员函数无法访问类的受保护成员

静态类与受保护的构造函数

派生类中的静态方法可以在 C++ 中调用受保护的构造函数吗?

如何在同一个类的静态方法中访问类的受保护变量?

PHP 从静态方法访问对象的受保护属性

受保护的静态方法访问