【Java 基础】10 抽象类和接口

1.抽象类和接口的引入

通过前一节我们已经了解了继承,知道了通过继承可以从父类继承下来一些东西

在这里插入图片描述

如果所有子类从父类那里继承下来的东西(方法 2)都需要重写,那么说明继承下来的具体功能的实现是无用的。这个时候就要使用 Java 为我们提供了一种特殊的父类称作抽象类啦,它只定义功能名称而不去定义具体实现细节,将其留给子类自己去实现。

在这里插入图片描述

这样,发现抽象父类相当于一个上帝,我决定了子类必须拥有某方法(方法 2),但是方法内具体有什么东西将由你们你们自己去实现。但是碍于 Java 是单继承的,就会有一定的局限性,所以又出现了一个全是空实现方法(抽象方法)的特殊抽象类,即接口。

在这里插入图片描述

使用了接口,那么所有的空实现方法(抽象方法),则都需要子类自己去实现啦。

接下来让我们看看 抽象类 和接口的具体使用吧!

2. 抽象类

抽象类是一种特殊的类,它不能被实例化,只能被用作其他类的基类

抽象类的主要作用是为子类提供一个通用的模板,并规定子类必须实现的抽象方法

示例代码:

// 抽象类
abstract class Shape {
    // 普通方法
    public void display() {
        System.out.println("This is a shape.");
    }

    // 抽象方法,子类必须实现
    abstract double area();
}

在上述例子中,Shape 是一个抽象类,它包含了一个普通方法 display() 和一个抽象方法 area()。抽象方法没有具体的实现,而是由子类来实现。

1)继承抽象类

子类继承抽象类时,必须实现抽象类中的所有抽象方法,否则子类也必须声明为抽象类

示例代码:

// 子类继承抽象类
class Circle extends Shape {
    private double radius;

    // 构造方法
    public Circle(double r) {
        radius = r;
    }

    // 实现抽象方法
    @Override
    double area() {
        return Math.PI * radius * radius;
    }
}

2)使用抽象类的实例

虽然抽象类不能被实例化,但可以通过子类的实例进行引用

示例代码:

public class Main {
    public static void main(String[] args) {
        Circle circle = new Circle(5.0);
        circle.display(); // 调用抽象类中的普通方法
        double area = circle.area(); // 调用抽象类中的抽象方法
        System.out.println("Area of the circle: " + area);
    }
}

在这个例子中,我们通过 Circle 类的实例来调用抽象类 Shape 中的方法

3)抽象类的特性

  • 包含一个抽象方法的类必须是抽象类
  • 抽象类和抽象方法都要使用 abstract 关键字声明
  • 抽象方法只需声明而不需要实现
  • 抽象类必须被子类继承,子类必须重写抽象类中的全部抽象方法(子类如果是抽象类除外)

3. 接口

接口(Interface)是一种抽象类型,它定义了一组抽象方法,但是不包含具体的实现

接口可以被类实现,使得类能够遵循接口定义的契约,实现接口的类必须提供接口中定义的所有方法

1)创建接口

使用 interface 关键字可以定义一个接口。接口中可以包含抽象方法、常量和默认方法

示例代码:

// 定义一个接口
interface Shape {
    // 抽象方法
    double area();

    // 常量
    double PI = 3.14;

    // 默认方法
    default void display() {
        System.out.println("This is a shape.");
    }
}

在上述例子中,Shape 是一个接口,定义了一个抽象方法 area()、一个常量 PI 和一个默认方法 display()

2)实现接口

类通过关键字 implements 实现接口,并提供接口中定义的所有方法的具体实现

示例代码:

// 实现接口
class Circle implements Shape {
    private double radius;

    // 构造方法
    public Circle(double r) {
        radius = r;
    }

    // 实现抽象方法
    @Override
    public double area() {
        return PI * radius * radius;
    }
}

在上述例子中,Circle 类通过 implements 实现了 Shape 接口,并提供了 area() 方法的具体实现。

3)使用接口

可以通过接口类型引用实现该接口的对象

示例代码:

public class Main {
    public static void main(String[] args) {
        Circle circle = new Circle(5.0);
        circle.display(); // 调用接口中的默认方法
        double area = circle.area(); // 调用接口中的抽象方法
        System.out.println("Area of the circle: " + area);
    }
}

在这个例子中,我们通过 Shape 接口类型引用了 Circle 类的对象

4)接口的特性

  • 一个类可以实现多个接口。
  • 接口可以继承(extends)其他接口。
  • 接口中的方法默认是公有的(public),不需要使用 public 修饰符。
  • 接口中的字段默认是常量,必须使用 public static final 修饰符。

4.抽象类和接口的区别

抽象类接口
定义抽象类是一种不能被实例化的类,它用于包含一些抽象方法和可以包含普通方法的类。抽象方法是没有具体实现的方法,需要在子类中被具体实现。接口是一种完全抽象的类型,它定义了一组抽象方法,但不包含实现。实现接口的类需要提供具体的实现。
关键字使用 abstract 关键字来声明抽象类,可以包含抽象方法和非抽象方法。使用 interface 关键字来声明接口。
构造方法抽象类可以有构造方法,它可以被子类调用。接口不能包含构造方法,因为接口不能被实例化。
访问修饰符抽象类的方法可以有各种访问修饰符,包括 public、protected、default、private。接口的方法默认为 public 抽象方法,不能有 private、protected、default 访问修饰符。
变量抽象类中可以包含实例变量、静态变量、常量等。接口中只能包含常量,即 public static final 修饰的变量。
继承一个类只能继承一个抽象类。一个类可以实现多个接口。

5.共同点

  • 抽象方法: 抽象类和接口都可以包含抽象方法,需要在子类或实现类中提供具体实现
  • 多态性: 抽象类和接口都支持多态性,子类或实现类可以替代抽象类或接口类型
  • 扩展性: 抽象类和接口都支持代码的扩展,通过子类或实现类的添加,可以扩展系统功能

6.如何选择

  • 是否需要构造方法: 如果你需要构造方法或者想要有构造方法的类,那么选择抽象类。接口不能包含构造方法。
  • 单继承 vs 多实现: 如果一个类需要继承多个类,那么选择接口。Java支持单继承,但可以实现多个接口。
  • 共享代码: 如果多个类之间有一些共享的代码,可以将这些代码放在一个抽象类中。如果只是希望定义一些规范,而不包含任何实现,那么选择接口。
  • 设计层次结构: 如果你需要设计一个类层次结构,并且希望子类共享一些通用行为,那么选择抽象类。
  • 解耦: 接口有助于实现类之间的解耦。如果你希望将实现类与接口解耦,使得系统更加灵活,那么选择接口。

总的来说,抽象类和接口各有其优势和适用场景。在设计时,根据具体需求选择合适的方式,有时也可以同时使用抽象类和接口来实现更灵活的设计。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值