你好!讓我們談談Java中的抽像類Java抽像類的具體例子——1

為什麼類被稱為“抽象”?

您可能還記得抽像是什麼——我們之前討論過 :) 如果您忘記了,不用擔心。請記住, OOP 原則說,在設計類和創建對象時,您應該只表示實體的主要屬性並丟棄次要屬性。例如,如果我們正在設計一個SchoolTeacher班級,身高可能不是教師的必要屬性。事實上,這個特徵對於老師來說並不重要。但是如果我們要創建一個BasketballPlayer類,那麼高度將是最重要的特徵之一。好吧,一個抽像類是一組未來類的最抽象、“粗糙的工件”。工件不能直接使用——太“粗糙”了。但它定義了未來類(抽像類的後代)將具有的某些特徵狀態和行為。

Java中抽像類的例子

考慮一個簡單的汽車示例:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
這就是最簡單的抽像類的樣子。如您所見,沒什麼特別的:) 為什麼我們需要這個?首先,它提供了我們所需實體的最抽象描述——汽車。abstract關鍵字在這裡意味著什麼。在現實世界中,沒有“只是一輛車”這樣的東西。有卡車、賽車、轎車、轎跑車和 SUV。我們的抽像類只是一個“藍圖”,我們稍後將使用它來創建特定的汽車類。

public class Sedan extends Car {
  
   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }
  
}
在許多方面,這與我們在繼承課程中談到的內容相似。只有在那種情況下,我們才有一個Car方法不是抽象的類。但是這樣的解決方案有幾個缺點,這些缺點在抽像類中是固定的。首先,不能創建抽像類的實例:

public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Java 的創建者是故意製作這個“功能”的。再次記住:抽像類只是未來“常規”類的藍圖。你不需要藍圖的副本,對吧?同樣,沒有必要創建抽像類的實例 :) 如果類Car不是抽象的,那麼我們可以輕鬆地創建它的實例:

public class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public void go() {
       // ...some logic
   }

   public  void brake() {
       // ...some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // This is okay. The car is created.
   }
}
目前,我們的程序中有某種無法理解的汽車。它不是卡車,不是賽車,也不是轎車,但並不清楚它是什麼。是現實中不存在的“只是一輛車”。同樣的例子也可以用在動物身上。想像一下,如果您的程序有Animal對象(“只是動物”)。目前尚不清楚它是什麼種類,屬於哪個家族,或者俱有什麼特徵。在節目中看到一個會很奇怪。自然界中沒有“只是動物”。只有狗、貓、狐狸、鼴鼠等。抽像類將我們從“只是對象”中拯救出來。它們為我們提供了基準狀態和行為。例如,所有汽車都必須有型號顏色最高時速,而且他們還必須能夠使用油門剎車。就是這樣。這是一個通用的抽象藍圖,您稍後將使用它來設計您需要的類。注意:抽像類中的兩個方法也是抽象的,也就是說它們根本沒有實現。原因是一樣的:抽像類不會為“只是汽車”創建“默認行為”。它們只是表明每輛車必須能夠做什麼。也就是說,如果您確實需要默認行為,則可以在抽像類中實現方法。Java 不禁止這樣做:

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Accelerating!");
   }

   public abstract void brake();
  
   // Getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
控制台輸出
Accelerating!
如您所見,我們在抽像類中實現了一個方法,但沒有實現另一個。這樣一來,我們Sedan類的行為就分為兩部分:如果我們調用它的gas()方法,行為是從抽象父類“拉上來”的Car,我們brake()Sedan類中實現方法。這是超級方便和靈活的。但是我們的類現在不那麼抽象了,是嗎?畢竟,它實際上實現了一半的方法。事實是——這是一個非常重要的特徵——即使一個類的方法是抽象的,它也是抽象的. 兩種方法中的一種,或千種方法中的一種——都沒關係。我們甚至可以實現所有方法,不留下任何抽象。結果將是一個沒有任何抽象方法的抽像類。原則上這是可能的——編譯器不會產生任何錯誤——但最好不要這樣做,因為它剝奪了抽像這個詞的意義。你的程序員夥伴看到這個也會很驚訝:/也就是說,如果一個方法被標記為抽象的,每個後代類都必須實現它或被聲明為抽象的。否則編譯器會報錯. 當然,每個類只能繼承一個抽像類,所以抽像類和普通類在繼承上沒有區別。我們繼承抽像類還是普通類並不重要——父類只能有一個。

為什麼Java沒有多類繼承

我們已經說過 Java 中沒有多重繼承,但我們並沒有真正深究為什麼。讓我們現在嘗試這樣做。事實上,如果 Java 確實具有多重繼承,那麼子類將無法決定選擇哪種行為。假設我們有兩個類:ToasterNuclearBomb

public class Toaster {
  
  
 public void on() {

       System.out.println("The toaster is on. We're toasting!");
   }
  
   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
如您所見,兩個類都有一個on()方法。對於烤麵包機,該方法開始烤麵包,但對於核彈,它會引發爆炸。呃哦:/現在想像一下你已經決定(不要問我為什麼!)在兩者之間創造一些東西。這是你的課MysteriousDevice:當然,這段代碼是行不通的。我們僅將其作為“可能發生的情況”的示例進行介紹:

public class MysteriousDevice extends Toster, NuclearBomb {

   public static void main(String[] args) {
      
       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // And what should happen here? Will we get toast or a nuclear apocalypse?
   }
}
讓我們看看我們有什麼。這個神秘裝置同時源自烤麵包機和核彈。兩者都有一個on()方法。on()因此,如果我們調用一個對象,則不清楚應該執行哪個實現MysteriousDevice。對像不會理解。最重要的是,NuclearBomb 沒有off()方法,所以如果我們沒有猜對,就不可能關閉設備。Java抽像類的具體例子-2這種“誤解”,在不清楚應該執行哪個行為時,正是 Java 的創造者拒絕多重繼承的原因。也就是說,您將了解到 Java 類可以實現許多接口。