是否可以使用最终的静态类方法?

问题描述:

我需要一个类来继承另一个类。我在基类中有一个静态函数_init(),我不希望该方法在派生类中继承。我尝试了final关键字,但它不起作用。我该怎么办?是否可以使用最终的静态类方法?

+0

如果您需要初始化代码,那么最好使用对象。 – str

+2

首先,您为什么不希望基类能够访问此方法?如果您不希望派生类访问它,请将其设为私有。第二个选项是在派生类中重写它。 – Zoidberg

+0

我想要基类访问该方法_init()但不是派生类! –

你误解了最后的意思。

OOP的基本原理之一是,如果一个类是另一个类的子类,那么该类将获得它继承的类的所有功能。你不能只继承一些超类的功能,它是全部或没有。

对此的理由有点棘手,但一旦你做了,你会意识到这是有道理的。也就是说,如果一段代码能够处理特定类的项目,那么它也必须能够处理该项目的任何子类。如果一个子类没有它的超类的所有功能,你就不能这么做。

例如,假设您有一个类定义了与支付网关的接口。由于所有支付网关都不相同,因此您无法(或者至少不应该)实施可与任何可用支付网关接口的单一类。但总的来说,支付网关的工作原理基本相同。系统会发送一个请求,其中包括用户的信用卡详细信息以及要从卡中扣款的金额。支付网关回复一条消息,说明支付是否被授权。

你会用一个抽象的超类来实现这种功能,这个抽象的超类定义了你如何与支付网关进行一般的接口连接,然后为每个你想要使用的支付网关(paypal,sagepay,whatever)创建一个子类。

由于所有这些子类都从相同的基类继承,所以您可以确定它们都实现了某些方法,并且可以将消息发送到这些方法而不用担心。只要您处理的付款类是抽象付款类的子类,那么一切都应该起作用。

如果其中一个子类无法从抽象超类实现某些东西,那么您无法确定是否向子类发送特定消息会起作用或抛出异常。这会使继承毫无意义。如果一个程序员支持我,那么他不能用他自己的实现来替换我最终的方法”。这并不意味着这些方法在子类中不可用,只是你不能改变它们。

如果您确实必须从子类中删除功能,您可以通过覆盖超类方法并用空方法(不执行任何操作)替换它来完成。但不要那样做,因为它会导致上述类型的问题。

通常,如果遇到在超类中有功能的情况,而您在子类中不需要这些功能,则代码异味会告诉您可能需要重新考虑设计。

+1

感谢哥们!为了这么好的解释! –

在POO中,如果一个B类继承了另一个A类,那么B类将包含来自A类的所有方法,这是POO遗产的基础。所以I don't want that method to be inherited in the derived class在这里没有意义。你应该看看另一种机制来做到这一点。

此外,是most的情况下,这种情况下(你不希望派生类继承一个方法)是一个标志,你的派生类应该不会继承,你应该在哪里使用另一个系统。

+0

你能提出一个吗?我正在使用单例结构来访问类并仅初始化它一次! –

+0

它高度依赖于你想要做什么,以及为什么你想要它。 – pomeh

+0

我希望基类只能被初始化一次..并且派生不会拥有_init()方法..我可以这样做吗?因为基类调用_init()静态函数时有关键数据。 –

检查这个例子:

 
class foo 
{ 
    private static $stuff = array('key1' => 1, 'key2' => 2); 

    public final static function getstuff() 
    { 
    return self::$stuff; 
    } 
} 

+0

我试过了......它不工作! :( –

你是做了错误的方式。

只是你想扩展类有方法的事实,意味着你违反了Liskov's substitution principle ..如果阅读是很难:这里是a picture解释它。

如果您有这种情况,当您必须在对象将其发布到应用程序之前执行某种“工作”时,则应该使用Factory/Builder。

class FooBuilder 
{ 
    public function create($external_condition) 
    { 
     $object = new Foo; 
     if ($external_condition->has_happened()) 
     { 
     $object->set_condition($external_condition); 
     }else{ 
     $object->do_something_else(); 
     } 
     return $object; 
    } 
} 

现在你总是通过FooBuilder,使广告类Foo的情况下,您扩展Foo,它不具有任何无用的方法。

此外,我会争辩说,类中的静态方法是过程编程的标志。而静态变量不过是包含在命名空间中伪装成类的全局变量。

+0

我明白了你的观点!关于Liskov替代原则..但是我怎么能得到这个场景的行动!有没有什么原则错过?有什么办法吗? –

+0

@TirthBodawala,这是你正在谈论的场景关于? –

我会同意pomeh在PHP中的OOP,我也想补充一点,当与方法一起使用时FINAL关键字实际上意味着该方法不能被覆盖。该方法将被继承。

静态意味着每个类一个,而不是每个对象一个,无论一个类可能存在多少个实例。这意味着您可以在不创建类的实例的情况下使用它们。静态方法隐式地是最终的,因为重写是基于对象的类型完成的,静态方法附加到类而不是对象。只要原始方法没有被声明为最终的,超类中的静态方法可以被子类中的另一个静态方法所遮蔽。但是,您无法用非静态方法重写静态方法。换句话说,您不能将静态方法更改为子类中的实例方法。

最终的类不能扩展,即最终的类可能不会被子类化。当它的类被继承时,最后的方法不能被覆盖。你不能改变最终变量的值(是一个常数)。