如何在Java中例項化抽象類?


抽象類是在Java中用“abstract”關鍵字宣告的類。抽象類是面向物件程式設計 (OOP) 四大原則之一“繼承”的概念。“繼承”指的是Java類的特性,其中一個稱為“子類”的類可以繼承父類(通常稱為“超類”)的所有屬性。

在Java中,抽象類指的是其他子類可以從中繼承的基礎超類。它可以包含抽象方法和非抽象方法。

演算法

  • 步驟1 - 識別類中具有預設實現或無實現的方法。

  • 步驟2 - 刪除這些方法的實現。

  • 步驟3 - 將abstract關鍵字新增到類宣告中。

  • 步驟4 - 將abstract關鍵字新增到步驟2中修改的方法宣告中。

  • 步驟5 - 如果類有任何需要初始化的例項變數,請新增一個建構函式來初始化它們。

  • 步驟6 - 更新抽象類的任何子類以實現抽象方法或自身成為抽象類。

語法

讓我們看看在Java中例項化抽象類的語法 -

// Abstract Class
abstract class Shape {
   public abstract void draw();
}

方法

由於抽象類是不完整的類,因此不能直接使用“new”關鍵字對其進行例項化。

  • 具體子類 - 為了正確例項化一個原本模稜兩可或不完整的抽象類,可以選擇使用一個具體子類。透過從這個父抽象類無縫擴充套件並實現其每個方法要求,使用者可以成功建立和實現這個新例項化的子類,而不會出現操作中的錯誤或不一致。

  • Lambda表示式 - 要從抽象類建立物件,您還有另一個選擇 - 使用lambda表示式為其所有抽象提供實現。然後根據這些簽名將此lambda建立分配給相容的功能介面變數。

例項化抽象類

讓我們來看一個示例程式碼片段,以瞭解抽象類的用法。第一個場景提供了一個帶有非抽象類的程式碼。

示例

class Shape {
   public void printName() {  
      System.out.println("I'm a shape"); 
   }
    
   public float area() {  
      return 0;  
   }
    
   public void printDetails() {  
      this.printName();
      System.out.println("... and my area is " + this.area());
   }
}

class Circle extends Shape {  
   private float radius;
    
   public Circle(float radius) {  
      this.radius = radius;
   }
    
   public void printName() {        
      System.out.println("I'm a circle");  
   }  
    
   public float area() {  
      return (float) (Math.PI * Math.pow(radius, 2));  
   }
}

class Rectangle extends Shape {  
   private float length;
   private float width;  
    
   public Rectangle(float length, float width) {
      this.length = length;  
      this.width = width;  
   }
    
   public void printName() {  
      System.out.println("I'm a rectangle");   
   } 
   
   public float area() {  
      return length * width;  
   }
}

public class Main {     
   public static void main(String[] args) {  
      Shape[] shapes = { new Circle(3.5f), new Rectangle(4.0f, 5.0f) };  
      for (Shape shape : shapes) {
         shape.printDetails();
      }
   }
}

輸出

I'm a circle
... and my area is 38.48451
I'm a rectangle
... and my area is 20.0

Circle和Rectangle類都繼承了“Shape”超類中的printName()、area()和printDetails()方法。但是,這兩個類都沒有重寫area()方法來提供自己的實現。

透過在Circle物件上呼叫printDetails()方法,輸出將為“我是一個圓……我的面積是38.48451”。同樣,在Rectangle物件上呼叫printDetails()方法將輸出“我是一個矩形……我的面積是20.0”。這確保了輸出反映了正確的形狀及其相應的面積,基於每個類中提供的具體實現。

示例1:具體子類

// With abstract class
abstract class Shape {
   public abstract void printName();
   public abstract float area();
   public void printDetails() {
      this.printName();
      System.out.println("... and my area is " + this.area());
   }
}

// Concrete class
class Circle extends Shape {
   private float radius;
   public Circle(float radius) {
      this.radius = radius;
   }
   public void printName() {
      System.out.print("I'm a circle");
   }
   public float area() {
      return (float) (Math.PI * Math.pow(radius, 2));
   }
}

// Concrete class
class Rectangle extends Shape {
   private float length;
   private float width;
   public Rectangle(float length, float width) {
      this.length = length;
      this.width = width;
   }
   public void printName() {
      System.out.print("I'm a rectangle");
   }
   public float area() {
      return length * width;
   }
}

// Main class
public class Main {
   public static void main(String[] args) {
      Shape[] shapes = { new Circle(10), new Rectangle(5, 10) };
      for (Shape shape : shapes) {
         shape.printDetails();
      }
   }
}

輸出

I'm a circle... and my area is 314.15927
I'm a rectangle... and my area is 50.0

在上面更新的程式碼中,Circle和Rectangle類已經實現了在“Shape”抽象類中定義的抽象方法printName()和area()。Shape類中的printDetails()方法能夠使用這些方法來列印形狀名稱及其各自的面積。

透過將Shape設為抽象類並定義抽象方法,我們確保擴充套件Shape類的任何類都必須為printName()和area()方法提供自己的實現。

示例2:Lambda表示式

interface Nameable {
   String getName();
}
 
abstract class Shape {
   private Nameable nameable;
 
   public Shape(Nameable nameable) {
      this.nameable = nameable;
   }
 
   public abstract float area();
 
   public void printDetails() {
      System.out.println("I'm a " + nameable.getName() + " ... and my area is " + this.area());
   }
}
 
class Circle extends Shape {
   private float radius;
 
   public Circle(float radius) {
      super(() -> "circle");
      this.radius = radius;
   }
 
   @Override
   public float area() {
      return (float) (Math.PI * Math.pow(radius, 2));
   }
}
 
class Rectangle extends Shape {
   private float width;
   private float height;
 
   public Rectangle(float width, float height) {
      super(() -> "rectangle");
      this.width = width;
      this.height = height;
   }
 
   @Override
   public float area() {
      return width * height;
   }
}
 
public class Main {
   public static void main(String[] args) {
      Shape[] shapes = { new Circle(10), new Rectangle(5, 10) };
      for (Shape shape : shapes) {
         shape.printDetails();
      }
   }
}

輸出

I'm a circle ... and my area is 314.15927
I'm a rectangle ... and my area is 50.0

在我們最近對這段程式碼的更新中,我們透過將Shape指定為抽象類並將其getName()函式內部化,引入了一種改進的方法。進一步的改進包括整合一個printName方法,該方法成功地利用getName()的資料來顯示每個形狀的名稱。關於Circle和Rectangle子類 - 它們現在使用lambda表示式重寫其對應的getNames,以便準確識別預期的形式。

結論

總之,抽象類只能透過其基子類例項化,而不能直接例項化。這是繼承的一個概念。

其背後的主要原因是抽象類不是其方法和物件的完整實現,並且子類使用它們來繼承。

更新於:2023年7月31日

797 次瀏覽

啟動您的職業生涯

透過完成課程獲得認證

開始
廣告
© . All rights reserved.