“你好,阿米戈!現在有一個話題我想你會經常用到。我說的是繼承。

對於外行來說,編程就像魔法一樣。所以讓我從一個類比開始……

假設你是一位魔術師,想要創造一匹飛馬。你可以試著召喚飛馬。但是由於飛馬不是自然產生的,所以你會很難過。你會有很多工作要做。從一匹馬開始並召喚一些翅膀會容易得多。

遺產。 繼承的優點 - 1

在編程中,我們稱這個過程為“繼承”。假設您需要編寫一個非常複雜的類。您可能會花很長時間從頭開始編寫代碼,然後執行冗長的測試來查找錯誤。但為什麼要用艱難的方式呢?不如四處看看,看看你要找的類是否已經存在?

假設您找到一個類,它實現了您需要的 80% 的功能。您只需將其代碼複製到您的課程中即可。但這會有幾個缺點:

1) 您找到的類可能已經被編譯成字節碼。您可能無法訪問其源代碼。

2) 你可能擁有該課程的源代碼,但也在一家公司工作,如果你使用別人的 6 行代碼,可能會被起訴數十億美元。然後他們會起訴你。

3)這導致大量代碼的不必要的重複。如果另一個類的作者發現了一個錯誤並修復了它,你仍然有這個錯誤。

有一個更優雅的解決方案,不需要獲得對原始類代碼的合法許可。在 Java 中,您可以簡單地將另一個類聲明為您的類的父類。這相當於將該類的代碼添加到您自己的類中。父類的所有數據和方法都會出現在你的類中。例如,您可以從“馬”繼承,添加“翅膀”,並獲得“飛馬座”。

遺產。 繼承的優點 - 2

“很有意思,請繼續。”

“繼承還有其他用途。假設您有十個非常相似的類。它們具有匹配的數據和方法。您可以創建一個特殊的基類,將數據(關聯的方法)移動到基類,並擁有這十個類繼承自它。換句話說,對於每個類,您表明它有一個父類,也稱為基類。”

“正如抽象的優點只有在封裝中才能真正體現出來一樣,繼承的優點被多態放大了。但是我明天再告訴你。今天讓我們看幾個繼承的例子。”

“假設我們正在編寫一個國際象棋程序。我們需要棋子類。你建議使用哪些類,阿米戈?”

“國王、王后、主教、騎士、車和典當。”

“很好。你沒有錯過任何東西。”

“你建議在這些類中存儲什麼數據?”

“每個棋子的棋盤位置(x 和 y)和價值。畢竟,有些棋子比其他棋子更有價值。”

“這些課程之間有什麼區別?”

“他們移動棋子的方式不同。他們的行為也不同。”

“是的。您可以將它們定義為這樣的類:”

class King
{
int x;
int y;
int worth;
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen
{
int x;
int y;
int worth;
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook
{
int x;
int y;
int worth;
void rookMove()
{
//code that defines,
//how the rook moves
}
}
class Knight
{
int x;
int y;
int worth;
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop
{
int x;
int y;
int worth;
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn
{
int x;
int y;
int worth;
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

“是的,這正是我要寫的。”

“但是看看如何使用繼承來編寫更少的代碼。我們可以將相同的方法和數據移動到一個公共類中。我們稱之為 ChessItem。創建 ChessItem 對像沒有意義,因為它們不對應於任何棋子。但是這堂課會非常有幫助:“

class King extends ChessItem
{
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen extends ChessItem
{
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook extends ChessItem
{
void rookMove()
{
//code that defines,
//how the rook moves
}
}
 class ChessItem
{
int x;
int y;
int worth;
}
 
class Knight extends ChessItem
{
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop extends ChessItem
{
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn extends ChessItem
{
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

“多麼有趣!”

“當然!在包含數千個不同對象和數百個類的項目中,收益尤其大。在這種情況下,正確選擇類不僅可以顯著簡化邏輯,還可以將所需代碼減少十倍。”

“那麼要繼承一個類,你需要做什麼?”

“聲明一個類後,我們使用關鍵字‘ extends ’,後面跟著父類的名稱。你只能繼承一個類。

遺產。 繼承的優點 - 3

圖片顯示了從“豬”繼承而來的“牛”。«Pig»繼承自«chicken»,«chicken»繼承自«egg»。每個班級只有一位家長!這種繼承並不總是合乎邏輯的。如果你只有一頭豬,但你真的需要一頭牛,程序員往往會忍不住把“豬”變成“牛”的慾望。

“但是如果我想繼承兩個類呢?我有什麼辦法嗎?!”

“不是真的。Java 類不支持實現的多重繼承:一個類只能有一個父類。但是存在類型的多重繼承,這意味著一個類可以實現多個接口。這稍微緩解了這個問題。 “

“我明白了。什麼是接口?”

“明天我會告訴你關於接口的事。現在,讓我們繼續研究繼承。”