通過避免繼承來避免破壞類的行爲
Java的優勢之一是繼承的概念,其中一個類可以從另一個類派生,但有時最好防止另一個類的繼承。 爲了防止繼承,在創建類時使用關鍵字“ final”。
例如,如果一個類可能被其他程序員使用,則如果創建的任何子類可能引起問題,則你可能希望防止繼承。 一個典型的例子是String類。 如果我們想創建一個String子類:
public class MyString extends String{
}
我們將面臨以下錯誤:
cannot inherit from final java.lang.String
String類的設計者意識到它不是繼承的候選者,因此阻止了對其進行擴展。
爲什麼要防止繼承?
防止繼承的主要原因是確保類的行爲方式不會被子類破壞。
假設我們有一個Account類和一個擴展它的子類OverdraftAccount。 類帳戶具有方法getBalance():
public double getBalance()
{
return this.balance;
}
至此,在我們的討論中,子類OverdraftAccount尚未覆蓋此方法。
(注意:有關使用此Account和OverdraftAccount類的另一討論,請參見如何將子類視爲超類)。
讓我們爲每個Account和OverdraftAccount類創建一個實例:
Account bobsAccount = new Account(10);
bobsAccount.depositMoney(50);
OverdraftAccount jimsAccount = new OverdraftAccount(15.05,500,0.05);
jimsAccount.depositMoney(50);
//create an array of Account objects
//we can include jimsAccount because we
//only want to treat it as an Account object
Account[] accounts = {bobsAccount, jimsAccount};
//for each account in the array, display the balance
for (Account a:accounts)
{
System.out.printf("The balance is %.2f%n", a.getBalance());
}
The output is:
The balance is 60.00
The balance is 65.05
一切似乎都按預期工作,在這裏。 但是,如果OverdraftAccount覆蓋方法getBalance()怎麼辦? 沒有什麼可以阻止它執行以下操作:
public class OverdraftAccount extends Account {
private double overdraftLimit;
private double overdraftFee;
//the rest of the class definition is not included
public double getBalance()
{
return 25.00;
}
}
如果再次執行上述示例代碼,則輸出將有所不同,因爲jimsAccount調用了OverdraftAccount類中的getBalance()行爲:
The output is:
The balance is 60.00
The balance is 25.00
不幸的是,子類OverdraftAccount將永遠不會提供正確的餘額,因爲我們已經通過繼承破壞了Account類的行爲。
如果您設計一個供其他程序員使用的類,請始終考慮任何潛在子類的含義。 這就是不能擴展String類的原因。 程序員必須知道,當他們創建一個String對象時,它總是會表現得像String一樣,這一點非常重要。
如何防止繼承
要阻止類擴展,類聲明必須明確聲明它不能被繼承。 這可以通過使用“ final”關鍵字來實現:
public final class Account {
}
這意味着Account類不能是超類,而OverdraftAccount類不能再作爲其子類。
有時,您可能希望僅限制超類的某些行爲,以避免子類損壞。 例如,OverdraftAccount仍然可以是Account的子類,但是應避免覆蓋getBalance()方法。
在這種情況下,使用方法聲明中的“ final”關鍵字:
public class Account {
private double balance;
//the rest of the class definition is not included
public final double getBalance()
{
return this.balance;
}
}
注意在類定義中如何不使用final關鍵字。 可以創建Account的子類,但是它們不能再覆蓋getBalance()方法。 任何調用該方法的代碼都可以確信它會按原始程序員的意圖工作。
喜歡這篇文章的可以點個贊,歡迎大家留言評論,記得關注我,每天持續更新技術乾貨、職場趣事、海量面試資料等等
> 如果你對java技術很感興趣也可以交流學習,共同學習進步。
不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代
文章寫道這裏,歡迎完善交流。最後奉上近期整理出來的一套完整的java架構思維導圖,分享給大家對照知識點參考學習。有更多JVM、Mysql、Tomcat、Spring Boot、Spring Cloud、Zookeeper、Kafka、RabbitMQ、RockerMQ、Redis、ELK、Git等Java乾貨