如何在 Java 中实例化抽象类?

javaobject oriented programmingprogramming更新于 2024/11/3 16:44:17

抽象类是在 Java 中用"Abstract"关键字声明的类。抽象类是面向对象编程 (OOP) 四大原则之一的概念,称为"继承"。继承是指 Java 类的一个特性,其中一个称为"子类"的类可以继承通常称为"超类"的父类的所有属性。

在 Java 中,抽象类是指其他子类可以从中继承的基超类。它可以包含抽象方法和非抽象方法。

算法

  • 步骤 1 - 识别类中具有默认或没有实现的方法。

  • 步骤 2 - 删除这些方法的实现。

  • 步骤 3 - 将 abstract 关键字添加到类声明中。

  • 步骤 4 - 将 abstract 关键字添加到在步骤 2 中修改的方法声明中。

  • 步骤 5 - 如果类具有任何需要初始化的实例变量,请添加构造函数来初始化它们。

  • 步骤 6 - 更新抽象类的任何子类以实现抽象方法或变为抽象本身。

语法

让我们看一下在 Java 中实例化抽象类的语法 -

// 抽象类
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:具体子类

// 使用抽象类
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,以便准确识别预期的形式。

结论

总之,抽象类只能通过其基子类实例化,而不能直接实例化。这是一个继承的概念。

这背后的主要原因是抽象类不是其方法和对象的完整实现,并且被子类用来从它们继承。


相关文章


有用资源