是否可以使用最终的静态类方法?
你误解了最后的意思。
OOP的基本原理之一是,如果一个类是另一个类的子类,那么该类将获得它继承的类的所有功能。你不能只继承一些超类的功能,它是全部或没有。
对此的理由有点棘手,但一旦你做了,你会意识到这是有道理的。也就是说,如果一段代码能够处理特定类的项目,那么它也必须能够处理该项目的任何子类。如果一个子类没有它的超类的所有功能,你就不能这么做。
例如,假设您有一个类定义了与支付网关的接口。由于所有支付网关都不相同,因此您无法(或者至少不应该)实施可与任何可用支付网关接口的单一类。但总的来说,支付网关的工作原理基本相同。系统会发送一个请求,其中包括用户的信用卡详细信息以及要从卡中扣款的金额。支付网关回复一条消息,说明支付是否被授权。
你会用一个抽象的超类来实现这种功能,这个抽象的超类定义了你如何与支付网关进行一般的接口连接,然后为每个你想要使用的支付网关(paypal,sagepay,whatever)创建一个子类。
由于所有这些子类都从相同的基类继承,所以您可以确定它们都实现了某些方法,并且可以将消息发送到这些方法而不用担心。只要您处理的付款类是抽象付款类的子类,那么一切都应该起作用。
如果其中一个子类无法从抽象超类实现某些东西,那么您无法确定是否向子类发送特定消息会起作用或抛出异常。这会使继承毫无意义。如果一个程序员支持我,那么他不能用他自己的实现来替换我最终的方法”。这并不意味着这些方法在子类中不可用,只是你不能改变它们。
如果您确实必须从子类中删除功能,您可以通过覆盖超类方法并用空方法(不执行任何操作)替换它来完成。但不要那样做,因为它会导致上述类型的问题。
通常,如果遇到在超类中有功能的情况,而您在子类中不需要这些功能,则代码异味会告诉您可能需要重新考虑设计。
感谢哥们!为了这么好的解释! –
在POO中,如果一个B类继承了另一个A类,那么B类将包含来自A类的所有方法,这是POO遗产的基础。所以I don't want that method to be inherited in the derived class
在这里没有意义。你应该看看另一种机制来做到这一点。
此外,是most
的情况下,这种情况下(你不希望派生类继承一个方法)是一个标志,你的派生类应该不会继承,你应该在哪里使用另一个系统。
你能提出一个吗?我正在使用单例结构来访问类并仅初始化它一次! –
它高度依赖于你想要做什么,以及为什么你想要它。 – pomeh
我希望基类只能被初始化一次..并且派生不会拥有_init()方法..我可以这样做吗?因为基类调用_init()静态函数时有关键数据。 –
检查这个例子:
class foo { private static $stuff = array('key1' => 1, 'key2' => 2); public final static function getstuff() { return self::$stuff; } }
我试过了......它不工作! :( –
你是做了错误的方式。
只是你想扩展类不有方法的事实,意味着你违反了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
,它不具有任何无用的方法。
此外,我会争辩说,类中的静态方法是过程编程的标志。而静态变量不过是包含在命名空间中伪装成类的全局变量。
我明白了你的观点!关于Liskov替代原则..但是我怎么能得到这个场景的行动!有没有什么原则错过?有什么办法吗? –
@TirthBodawala,这是你正在谈论的场景关于? –
我会同意pomeh在PHP中的OOP,我也想补充一点,当与方法一起使用时FINAL关键字实际上意味着该方法不能被覆盖。该方法将被继承。
静态意味着每个类一个,而不是每个对象一个,无论一个类可能存在多少个实例。这意味着您可以在不创建类的实例的情况下使用它们。静态方法隐式地是最终的,因为重写是基于对象的类型完成的,静态方法附加到类而不是对象。只要原始方法没有被声明为最终的,超类中的静态方法可以被子类中的另一个静态方法所遮蔽。但是,您无法用非静态方法重写静态方法。换句话说,您不能将静态方法更改为子类中的实例方法。
最终的类不能扩展,即最终的类可能不会被子类化。当它的类被继承时,最后的方法不能被覆盖。你不能改变最终变量的值(是一个常数)。
如果您需要初始化代码,那么最好使用对象。 – str
首先,您为什么不希望基类能够访问此方法?如果您不希望派生类访问它,请将其设为私有。第二个选项是在派生类中重写它。 – Zoidberg
我想要基类访问该方法_init()但不是派生类! –