繁体   English   中英

使用子类和抽象父类中受保护的成员变量

[英]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属性,您可以:

  1. 将其声明为protected (您的教授似乎不太喜欢它,但是我认为他缺乏适当的解释)
  2. 在超类中声明一个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM