![](/img/trans.png)
[英]Protected abstract methods not visible in child class wrapping instance of parent
[英]The use of protected member variables from child class and abstract parent
根据我们的教授的说法,应不惜一切代价避免使用受保护的可见性。 但是,我对为什么有些疑惑。 说我们有这个例子:
public abstract class Animal {
private int maxSpeed;
public Animal() {}
public abstract void setMaxSpeed();
}
每个Animal
具有最大速度的位置,稍后需要在子类中定义最大速度。 但是,将其抛出:
public class Tutrle extends Animal {
public Tutrle() {
}
@Override
public void setMaxSpeed() {
}
}
无法从覆盖的setMaxSpeed()
方法内访问maxSpeed
变量。 尽管一种解决方案是通过Animal
类的构造函数设置maxSpeed
,但将maxSpeed
变量设置为protected
并让以后所有定义的所有子子类都可以访问它不是更好吗?
由于maxSpeed
成员是在Animal
类中定义的,因此该类具有可以对其进行设置的非抽象方法就更有意义了:
public void setMaxSpeed(int maxSpeed)
{
this.maxSpeed = maxSpeed;
}
子类(例如Turtle
)可以重写此方法以添加逻辑,但是它们应调用基类来设置值。
@Override
public void setMaxSpeed(int maxSpeed)
{
if (maxSpeed > 5)
throw new SomeException();
super.setMaxSpeed(maxSpeed);
}
如果setMaxSpeed()
保持抽象状态,则对于实现此方法的每个子类来说,拥有自己的maxSpeed
成员会更有意义。
为了从子类访问maxSpeed
属性,您可以:
protected
(您的教授似乎不太喜欢它,但是我认为他缺乏适当的解释) getMaxSpeed()
方法:如果需要从层次结构外部知道最大速度,则将其声明为public
; 否则,将其声明为protected
,以便子类(特定动物,例如Turtle
)可以知道其最大速度。 我同意@Eran的观点,即在Animal
超类中不应将setMaxSpeed()
方法声明为abstract
方法,如果子类在最大速度为0时需要进行特定处理,则可以从其自己的setMaxSpeed
方法中调用super.setMaxSpeed()
。被设置。
关于为什么声称“不惜一切代价避免使用protected
”或危险的等原因,请参阅此惊人的时事通讯文章 。 我个人的观点是,做出这样的主张,或者至少是过度反应是错误的。 但是,如文章中所述:
我们应该尝试仅从构造函数内部调用私有方法或最终方法。 原因是Java总是调用最派生的方法,这意味着我们可以在半初始化对象上调用方法。
这意味着,如果您从父类的构造函数中调用protected
方法,并且如果在子类之一中重写了protected
方法,则该方法中的代码将在该类的其余部分完全初始化之前运行。可能导致讨厌的错误:
class Animal {
protected int maxSpeed;
protected SomeClass someClass;
protected Animal(int maxSpeed, SomeClass someClass) {
this.setMaxSpeed(maxSpeed); // call to subclass method
this.someClass = someClass;
}
public abstract void setMaxSpeed(int maxSpeed); // could also be protected
}
class Turtle extends Animal {
@Override
public void setMaxSpeed(int maxSpeed) {
if (this.someClass.checkIfMaxSpeedMustBeDoubled()) { // throws NPE
this.maxSpeed = maxSpeed * 2;
} else {
this.maxSpeed = maxSpeed;
}
}
}
在这个非常简单的示例中, this.someClass.checkIfMaxSpeedMustBeDoubled()
引发NullPointerException
因为this.someClass
尚未在Animal
超类中初始化。 使用protected
成员时,这种错误非常普遍,但是声称应该避免protected
是荒谬的。 请小心,仅从超类的构造函数中调用private
方法或final
方法,您会没事的。
这取决于需求,如果希望maxSpeed
变量应出现在所有子类中,则将该变量放在maxSpeed
类中,然后在子类中重用该变量。 为此,您必须通过子类构造函数初始化该变量,并将该变量的修饰符更改为protected。
但是,如果子类仅与您的子类相关,则最好在子类中创建变量,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.