如何强制实现受保护的静态函数 [英] How to force an implementation of a protected static function

查看:27
本文介绍了如何强制实现受保护的静态函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to write an abstract class (or interface) which forces the extending class to implement a protected static function. But this is neither possible with an abstract class nor an interface.

错误:

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

有什么想法可以实现吗?

Any ideas how to accomplish that?

更新

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

The purpose is basically to call the public function statically. This way the class does not need to be instanciated. It is also not necessary to make _doSpecificStuff() callable from class-external code.

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

        static::_doSpecificStuff();
    }

    // sth like that would be nice to have:
    abstract static protected function _doSpecificStuff();
}

推荐答案

从理论和实践的角度来看,实际上没有必要声明一个静态方法抽象.

From a theoretical as well as a practical standpoint, there's no real need to declare a static method abstract.

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

Abstract methods are there to have a child class fill in a blank. That's typically because the parent class (the original abstract class) does some generic operation, but can/must be adapted to certain specific situations and can thus force child classes to implement only this particular variable part in the otherwise generic algorithm. Abstract methods are supposed to be a blank spot within a larger algorithm.

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

A parent method would call implementations of its abstract methods without knowing or caring who implements them or how they're implemented:

abstract class Foo {

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

    abstract protected function doSomethingSpecific();

}

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

Foo doesn't care who or what fills in the blank doSomethingSpecific, it just relies on it being there and its signature, which abstract enforces. The specific object which implements this method or how it implements it is variable. This is important and is at the core of the issue.

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

Declaring a static method abstract is pretty useless in this scenario. Any static method can just as well be implemented as a non-static method, so there's no use for it here. If the class itself is supposed to call the abstract method as part of a larger generic algorithm as described above, there's no need for a static method.

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

So the only scenario left for a static method is for a public static method which is callable from anywhere:

abstract class Foo {

    abstract public static function bar();

}

class Baz extends Foo {

    public static function bar() { ... }

}

Baz::bar();

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

The thing is, since the abstract class Foo is not itself calling this function but this function is only called from external code, you're not really talking about a fill-in-the-blank method, you're talking about an interface. So, you should be using an interface instead.
But even there, since you have to type the specific class name in your source code, hardcoded, there's little point for an interface as well.

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

The point of declaring an interface or abstract method signature is that you want to fix the method signature so any code can call that particular method without caring what object it's calling it on in particular. But since you have to hardcode the class name, there's no variability in the object you're calling it on. If you type Baz::bar(), you know exactly what class you're calling what method on. Therefore there's little point in abstracting the interface/signature.

比较:

interface FooInterface {

    public function bar();

}

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

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

The function baz can rely on its argument having a bar() method due to the interface declaration. The specific object that's implementing the method is irrelevant and will vary.

abstract class Foo {

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

    abstract protected function doSomethingSpecific();

}

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

The class Foo can rely on it having the doSomethingSpecific method. The specific object that's implementing the method is irrelevant and will vary.

abstract class Foo {

    abstract public static function bar();

}

class Baz extends Foo {

    public static function bar() { ... }

}

Baz::bar();

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

What exactly are you relying on or abstracting here? You can be pretty darn sure Baz will have the method bar() every time, because you're only ever calling it on the same hardcoded class. Nothing is variable here.

这篇关于如何强制实现受保护的静态函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆