112. Java 继承 - 抽象方法和类

112. Java 继承 - 抽象方法和类

抽象方法和类

抽象类 是一个声明为 abstract 的类,它不能被直接实例化。抽象类可能包含抽象方法,也可以没有抽象方法。抽象方法是没有具体实现的方法,它仅仅声明了方法的签名,而没有提供方法的实际代码实现。抽象类的作用是为子类提供一个模板,让子类根据自己的需要来实现这些抽象方法。

抽象方法

抽象方法的声明方式如下:

java 复制代码
abstract void moveTo(double deltaX, double deltaY);

在上面的例子中,moveTo 是一个抽象方法,它没有方法体。它仅定义了方法的签名,而没有提供实现。任何继承此抽象类的子类都必须实现该方法,除非子类本身也是抽象类。

抽象类

如果一个类中包含抽象方法,那么该类也必须声明为 abstract,如下所示:

java 复制代码
public abstract class GraphicObject {
    // 声明字段
    // 声明非抽象方法
    abstract void draw();
}

在这个例子中,GraphicObject 是一个抽象类,它包含一个抽象方法 draw(),要求所有继承该类的子类必须实现 draw() 方法。

注意 :接口中的方法默认都是抽象的,除非明确声明为 defaultstatic。因此,接口方法不需要显式地使用 abstract 关键字。

抽象类与接口的比较

抽象类和接口有许多相似之处,都是用于描述类的行为和结构,但它们有显著的不同之处。

抽象类

  • 不能实例化:不能创建抽象类的实例。
  • 可以包含字段 :可以包含字段,包括非 static 和非 final 字段。
  • 可以包含方法 :可以包含具体实现的非 static 和非 final 方法。
  • 继承限制:一个类只能继承一个抽象类。

接口

  • 可以多继承:一个类可以实现多个接口。
  • 方法默认是 abstract :接口中的方法默认是抽象的,除非声明为 defaultstatic
  • 字段 :接口中的字段默认是 public static final

何时使用抽象类,何时使用接口?

  • 使用抽象类 :如果希望在多个相关的类之间共享代码,或者类需要多个常用的字段或方法,或者需要使用 protectedprivate 等访问修饰符,那么应使用抽象类。
  • 使用接口 :如果期望不同的类实现相同的行为,但这些类没有任何继承关系(例如,ComparableCloneable 接口),或者希望支持多重继承时,应使用接口。

示例:

JDK 中的 AbstractMap 类就是一个抽象类,包含了许多可以共享的操作(如 get(), put() 方法)。具体实现如 HashMapTreeMap 继承了该类并提供了具体实现。

另一方面,HashMap 类实现了多个接口,如 SerializableCloneableMap<K, V>。这意味着 HashMap 的实例不仅是一个映射结构,还具备克隆和序列化的能力。

抽象类示例

假设我们正在开发一个面向对象的绘图应用程序,需要绘制不同的图形对象,如圆形、矩形、线条等。这些图形对象有一些共同的状态(如位置、颜色)和行为(如移动、旋转、调整大小、绘制)。但是,每种图形对象的绘制和调整大小方式可能不同。

定义抽象类

java 复制代码
abstract class GraphicObject {
    int x, y;  // 图形的坐标
    String color;  // 图形的颜色
    
    // 共享的行为
    void moveTo(int newX, int newY) {
        x = newX;
        y = newY;
    }

    // 需要子类实现的行为
    abstract void draw();
    abstract void resize();
}

在上面的例子中,GraphicObject 是一个抽象类,包含了所有图形对象共有的状态(如 x, y, color)和方法(如 moveTo)。但是,drawresize 方法是抽象的,因为每种图形对象的绘制和调整大小方式不同,需要在子类中实现。

子类实现抽象方法

java 复制代码
class Circle extends GraphicObject {
    void draw() {
        System.out.println("Drawing a Circle at (" + x + ", " + y + ")");
    }

    void resize() {
        System.out.println("Resizing the Circle.");
    }
}

class Rectangle extends GraphicObject {
    void draw() {
        System.out.println("Drawing a Rectangle at (" + x + ", " + y + ")");
    }

    void resize() {
        System.out.println("Resizing the Rectangle.");
    }
}

在上面的代码中,CircleRectangleGraphicObject 的子类,它们实现了 draw()resize() 方法。每个子类根据其图形的不同特点提供了具体的实现。

当抽象类实现接口时

一个抽象类可以实现一个接口,但不需要实现接口中的所有方法。子类可以继承抽象类并实现接口中剩余的未实现方法。

例如:

java 复制代码
abstract class X implements Y {
    // 实现接口 Y 中的部分方法
}

class XX extends X {
    // 完成实现接口 Y 中剩余的方法
}

在这个例子中,类 X 实现了接口 Y,但是它没有实现接口中的所有方法,因此 X 被声明为抽象类。类 XX 继承了 X 并实现了接口 Y 中剩余的方法。

抽象类的静态成员

虽然抽象类不能被实例化,但它仍然可以拥有静态字段和静态方法。您可以像普通类一样使用静态方法,例如:

java 复制代码
abstract class AbstractClass {
    static void staticMethod() {
        System.out.println("Static method in abstract class");
    }
}

public class TestClass {
    public static void main(String[] args) {
        AbstractClass.staticMethod();  // 直接通过类名调用静态方法
    }
}

静态方法和字段是类级别的,而不是实例级别的,因此您不需要实例化类就可以访问它们。


通过这些示例和扩展,抽象类和方法的概念应该更加清晰了。抽象类是面向对象编程中非常重要的一部分,它帮助我们建立类之间的共性,并在不同的子类中实现多态性。

相关推荐
来杯三花豆奶6 分钟前
Vue 2 中 Store (Vuex) 从入门到精通
前端·javascript·vue.js
Lethehong6 分钟前
React构建实时股票分析系统:蓝耘MaaS平台与DeepSeek-V3.2的集成实践
前端·react.js·前端框架·蓝耘mcp·蓝耘元生代·蓝耘maas
LSL666_8 分钟前
1 验证码
java·服务器·前端·redis·验证码
Angletank12 分钟前
SpringBoot中ORM组件通过JAP组件的使用
spring boot·后端·orm·jpa
moxiaoran575316 分钟前
Go语言的map
开发语言·后端·golang
小信啊啊17 分钟前
Go语言数组
开发语言·后端·golang
白宇横流学长17 分钟前
基于SpringBoot实现的零食销售商城设计与实现【源码+文档】
java·spring boot·后端
superman超哥19 分钟前
仓颉语言中异常捕获机制的深度剖析与工程实践
c语言·开发语言·后端·python·仓颉
驱动探索者23 分钟前
[缩略语大全]之[INTEL]篇
java·后端·spring·intel
少油少盐不要辣24 分钟前
前端如何处理AI模型返回的流数据
前端·javascript·人工智能