1.飛馬座

讓我們更深入地了解一下OOP的第三個原則:繼承。這是一個非常有趣的主題,您將經常使用它。對於外行來說,編程與魔術沒有區別。因此,讓我們從一個有趣的類比開始……;

假設您是一位想要創造一匹飛馬的巫師。一方面,你可以試著召喚飛馬。但由於天馬在自然界中不存在,這將是非常困難的。你將不得不自己做很多事情。騎馬並召喚它的翅膀要容易得多。

在編程中,這個過程被稱為“繼承”。假設您需要編寫一個非常複雜的類。從頭開始編寫代碼然後長時間測試所有內容以查找錯誤需要很長時間。為什麼要走艱難的路?最好看看這樣的類是否已經存在。

假設您找到一個類,其方法實現了您需要的 80% 的功能。接下來你會用它做什麼?您可以將其代碼複製到您的班級中。但是這個解決方案有幾個缺點:

  1. 您找到的類可能已經編譯成字節碼,您可能無法訪問其源代碼。
  2. 該類的源代碼是可用的,但你為一家公司工作,即使使用別人的 6 行代碼也可能被起訴數十億美元。然後你的雇主會起訴你。
  3. 大量代碼的不必要的重複。此外,如果外部類的作者發現其中的錯誤並修復它,您仍然會遇到錯誤。

有一個更優雅的解決方案,它不需要獲得對原始類代碼的合法訪問權限。在 Java 中,您可以簡單地將那個類聲明為您的類的父類。這相當於將該類的代碼添加到您自己的代碼中。您的類將看到父類的所有數據和所有方法。例如,您可以這樣做:我們繼承“馬”,然後添加“翅膀”以獲得“飛馬座”


2.公共基類

繼承也可以用於其他目的。假設您有十個非常相似的課程。他們有相同的數據和方法。您可以創建一個特殊的基類,將數據(和關聯的方法)移動到這個基類中,並將這十個類聲明為後代。也就是說,在每個類中都標明其父類就是這個基類。

正如抽象的優點只有通過側面封裝才能體現出來一樣,在使用多態性時繼承的優點也會大大增強。但是你稍後會了解到這一點。今天我們將看幾個使用繼承的例子。

棋子

假設我們正在編寫一個與人類用戶下棋的程序。因此,我們需要類來表示棋子。他們是什麼班級?

如果您曾經下過國際象棋,那麼顯而易見的答案就是國王、王后、象、馬、車和兵。

但是類本身仍然需要存儲關於每件作品的信息。例如,x 和 y 坐標,以及棋子的值。畢竟,有些作品比其他作品更有價值。

此外,棋子的移動方式不同,這意味著類將實現不同的行為。以下是如何將它們定義為類:

class King
{
   int x;
   int y;
   int worth;

   void kingMove()
   {
     // Code that decides
     // how to move
     // the king
   }
}
class Queen
{
   int x;
   int y;
   int worth;

   void queenMove()
   {
     // Code that decides
     // how to move
     // the queen
   }
}
class Rook
{
   int x;
   int y;
   int worth;

   void rookMove()
   {
     // Code that decides
     // how to move
     // the rook
   }
}
class Knight
{
   int x;
   int y;
   int worth;

   void knightMove()
   {
     // Code that decides
     // how to move
     // the knight
   }
}
class Bishop
{
   int x;
   int y;
   int worth;

   void bishopMove()
   {
     // Code that decides
     // how to move
     // the bishop
   }
}
class Pawn
{
   int x;
   int y;
   int worth;

   void pawnMove()
   {
     // Code that decides
     // how to move
     // the pawn
   }
}

這是對棋子的非常原始的描述。

公共基類

下面介紹如何使用繼承來減少代碼量。我們可以把通用的方法和數據放到一個通用的類中。我們稱之為ChessItem. 創建的對像ChessItem class沒有意義,因為該類不對應於任何棋子。也就是說,該課程將證明非常有用:

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

這是簡化類似對象代碼的好方法。 當項目中有數千個不同的對象和數百個類時,好處尤其明顯。所以正確選擇父(基)類讓你不僅可以大大簡化邏輯,還可以將代碼減少十倍。


3.類繼承——extends

那麼繼承一個類需要什麼呢?一個類要繼承另一個類,需要extends在子類聲明後寫上關鍵字,然後寫上父類的名字。它通常看起來像這樣:

class Descendant extends Parent

這是您在聲明 Descendant 類時需要編寫的內容。順便說一句,一個類只能繼承一個類。

在圖片中,我們看到一頭牛繼承了豬,豬繼承了雞,雞繼承了雞蛋。只有一個父母!這種繼承並不總是合乎邏輯的。但是當你只有一頭豬而你真的需要一頭牛時,程序員往往無法抗拒將豬變成牛的衝動。

Java沒有多重繼承:一個類不能繼承兩個類。每個類只能有一個父類。如果未指定父類,則父類為Object.

也就是說,Java 確實具有接口的多重繼承。這稍微緩解了這個問題。稍後我們會討論接口,但現在讓我們繼續探索繼承。