![](/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.