Java 使用子类和抽象父类中受保护的成员变量
根据我们的教授,应该不惜一切代价避免使用受保护的可见性。然而,我有点不解为什么。比如说我们有:Java 使用子类和抽象父类中受保护的成员变量,java,polymorphism,Java,Polymorphism,根据我们的教授,应该不惜一切代价避免使用受保护的可见性。然而,我有点不解为什么。比如说我们有: public abstract class Animal { private int maxSpeed; public Animal() {} public abstract void setMaxSpeed(); } 其中,每个动物都有一个最大速度,该速度需要在以后的子类中定义。然而,把这个放进去: public class Tutrle extends Anim
public abstract class Animal {
private int maxSpeed;
public Animal() {}
public abstract void setMaxSpeed();
}
其中,每个动物
都有一个最大速度,该速度需要在以后的子类中定义。然而,把这个放进去:
public class Tutrle extends Animal {
public Tutrle() {
}
@Override
public void setMaxSpeed() {
}
}
无法从重写的
setMaxSpeed()
方法中访问maxSpeed
变量。虽然解决方案是通过Animal
类的构造函数设置maxSpeed
,但最好将maxSpeed
变量设置为protected
,并使其可供以后定义的所有子类访问?这取决于需求,如果您希望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
属性,您可以:
getMaxSpeed()
方法:如果需要从层次结构外部知道最大速度,则将其声明为public
;否则,将其声明为受保护
,以便子类(特定动物,如您的海龟
)可以知道它们的最大速度setMaxSpeed()
方法不应在Animal
超类中声明为abstract
,如果子类在设置其最大速度时需要进行特定处理,则可以从自己的setMaxSpeed()方法调用super.setMaxSpeed()
关于为什么声称使用受保护的
是“不惜一切代价避免的”或危险的,请参阅此。我个人的观点是,提出这样的主张是错误的,或者至少是反应过度。然而,正如文章中所解释的:
我们应该尝试只从构造函数内部调用私有或final方法。原因是Java总是调用最派生的方法,这意味着我们可以在半初始化的对象上调用方法
这意味着,如果从超类的构造函数中调用受保护的
方法,并且如果在其中一个子类中重写了受保护的
方法,则该方法中的代码将在类的其余部分完全初始化之前运行,这可能会导致严重错误:
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.CheckIfMaxSpeedMustedoubled()
抛出一个NullPointerException
,因为this.someClass
尚未在Animal
超类中初始化。这种错误在使用受保护的
成员时非常常见,但声称应避免受保护的
是荒谬的。只要小心,只从超类的构造函数中调用private
或final
方法,就可以了。在这种特殊情况下,我会将maxSpeed
字段移到一个具体的类中。我不同意,@ILoveCodingmaxSpeed
应该是每个动物定义的一部分,这就是为什么位于abstract
类中的原因。然而,我会为它的价值引入一个protected
getter。声称“应该不惜一切代价避免使用protectedvisibility”有点过分。你的教授在这件事上是原教旨主义者。然而,protected
确实会导致一些OO设计错误。