簡體   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