CodeGym /課程 /Java 核心 /遺產。繼承的優勢

遺產。繼承的優勢

Java 核心
等級 1 , 課堂 5
開放

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

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

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

遺產。 繼承的優點 - 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 類不支持實現的多重繼承:一個類只能有一個父類。但是存在類型的多重繼承,這意味著一個類可以實現多個接口。這稍微緩解了這個問題。 “

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

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

3
任務
Java 核心, 等級 1, 課堂 5
上鎖
Code entry
Sometimes you don't need to think, you just need to hammer it out! As paradoxical as it may seem, sometimes your fingers will "remember" better than your conscious mind. That's why while training at the secret CodeGym center you will sometimes encounter tasks that require you to enter code. By entering code, you get used to the syntax and assimilate some material. What's more, you combat laziness.
3
任務
Java 核心, 等級 1, 課堂 5
上鎖
Code typing
Your attention, please! Now recruiting code entry personnel for CodeGym. Turn up your focus, let your fingers relax, read the code, and then... type it into the appropriate box. Code entry is far from a useless exercise, though it might seem so at first glance: it allows a beginner to get used to and remember syntax (modern IDEs seldom make this possible).
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION