- 1.基本介绍
- 1.1 抽象类
- 1.2 接口
- 2. 抽象类与接口的异同点
- 2.1 相同点
- 2.2 不同点
- 2.3 代码示例
- 3. 抽象类和接口的使用场景
- 3.1 抽象类的使用场景
- 3.2 接口的使用场景
-
概述:当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,类中如果有抽象方法,那么该类必须定义为抽象类,它用来描述一种类型应该具备的基本特征与功能。
-
细节:
(1)抽象类和抽象方法必须用 abstract 关键字修饰
(2)抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
(3)抽象类 不能直接实例化(其可以通过子类对象实例化,即抽象类多态)
(4)抽象类的子类要么重写抽象类中的所有抽象方法,要么是抽象类
(5)抽象方法不能使用private、final 和 static 来修饰,因为这些关键字都是和重写相违背的 -
语法:
//抽象类
访问修饰符 abstract 类名 {
}
//抽象方法
访问修饰符 abstract 返回类型 方法名(参数列表); //没有方法体
- 代码示例:
说明:
编写一个 抽象类 Shape 类,包含 抽象方法 getArea(求面积)、show(输出对象信息)。设计 Rectangle 类 继承 Shape 类,要求实现父类的两个抽象方法。最后在 Test01 里测试。
(1)抽象类 Shape 类
package abstract_;
//抽象类 Shape 类
abstract class Shape {
//抽象方法
public abstract double getArea(); //求面积
public abstract void show(); //输出
}
(2)子类 Rectangle 类
package abstract_;
//子类 Rectangle 类 继承 抽象类 Shape 类
public class Rectangle extends Shape {
private double width;
private double height;
//有参构造
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
//实现父类的抽象方法
@Override
public double getArea() {
return width * height;
}
@Override
public void show() {
System.out.println("Width: " + width + " Height: " + height);
}
}
(3)测试类 Test01 类
package abstract_;
//测试 抽象类
public class Test01 {
public static void main(String[] args) {
//采用多态方式实例化抽象类,向上转型
Shape s1 = new Rectangle(3, 4);
//调用方法
s1.show();
System.out.println("Area: " + s1.getArea());
}
}
(4)运行结果
Width: 3.0 Height: 4.0 Area: 12.01.2 接口
-
概述:接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用,即给出一些没有实现的方法,封装到一起,到某个类型要使用的时候,再根据具体情况,把这些方法写出来。Java 中的接口更多的体现在对行为的抽象。
-
细节:
(1)接口用关键字 interface 修饰
(2)类 实现 接口用 implements 表示
(3)接口 不能直接实例化(其可以通过实现类对象实例化,即接口多态)
(4)接口的实现类要么重写接口中的所有抽象方法,要么是抽象类
(5)一个类同时可以实现多个接口
(6)接口中所有的方法是 public 方法 -
语法:
public interface 接口名 {
//属性
//抽象方法
}
class 类名 implements 接口 {
//自己属性
//自己方法
//必须实现的接口的抽象方法
}
- 代码示例:
说明:
定义一个 接口 IShape ,包含 抽象方法 getArea(求面积)、show(输出对象信息)。设计 Rectangle 类 实现 IShape,最后在 Test02 里测试。
(1)接口 IShape
package interface_;
//定义 IShape 接口
public interface IShape {
//抽象方法,省略了 abstract 关键字
public double getArea(); //求面积
public void show(); //输出
}
(2)子类 Rectangle 类
package interface_;
// Rectangle 类 实现 接口 IShape
public class Rectangle implements IShape {
private double width;
private double height;
//有参构造
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
//实现接口里的抽象方法
@Override
public double getArea() {
return width * height;
}
@Override
public void show() {
System.out.println("Width: " + width + " Height: " + height);
}
}
(3)测试类 Test02 类
package interface_;
//测试 接口
public class Test02 {
public static void main(String[] args) {
//采用多态方式实例化接口,向上转型
IShape s1 = new Rectangle(3, 4);
//调用方法
s1.show();
System.out.println("Area: " + s1.getArea());
}
}
(4)运行结果
Width: 3.0 Height: 4.0 Area: 12.02. 抽象类与接口的异同点 2.1 相同点
- 接口和抽象类 都不能直接实例化,主要用于被其他类实现和继承
- 接口的实现类和抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化
| 不同点 | 抽象类 | 接口 |
|---|---|---|
| 关键字 | abstract class | interface |
| 字段 | 无限制 | 必须是 public、static 和 final 的 |
| 方法 | 既可以含普通方法,也可以含抽象方法 | 只能含抽象方法,且必须是 public 的 |
| 继承/实现 | 只能被类或者抽象类继承 | 既可以被接口继承,也能被类或抽象类实现 |
| 多重继承 | 不支持 | 可以继承多个父接口 |
| 常见设计模式 | 模板设计 | 工厂设计、代理设计 |
说明:
- 编写 抽象类 Person 类,定义 Student 类 和 Teacher 类作为子类继承该抽象类;
- Person 类拥有属性 name(姓名) 以及抽象方法 sleep() ;
- 定义一个接口 ISwim ,实现 部分 老师和学生 会游泳 的功能;
- 编写 SwimStudent 类 和 SwimTeacher 类 分别 继承 Sudent 类 和 Teacher 类 并 实现接口 ISwim;
- 最后在 Test03 里测试。
代码示例:
(1)抽象类 Person 类
package abstractvsinterface;
//抽象类 Person 类
public abstract class Person {
private String name; //姓名
//无参构造
public Person() {
}
//有参构造
public Person(String name) {
this.name = name;
}
//getter and setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//抽象方法 sleep()
public abstract void sleep();
}
(2)Person 类的子类 Student 类
package abstractvsinterface;
//子类 Student 类 继承 抽象类 Person 类
public class Student extends Person {
//无参构造
public Student() {
}
//有参构造
public Student(String name) {
super(name);
}
//实现父类的抽象方法
public void sleep() {
System.out.println("学生回宿舍睡觉!");
}
}
(3)Person 类的子类 Teacher 类
package abstractvsinterface;
public class Teacher extends Person {
//无参构造
public Teacher() {
}
//有参构造
public Teacher(String name) {
super(name);
}
public void sleep() {
System.out.println("老师回学校公寓睡觉!");
}
}
(4)接口 ISwim
package abstractvsinterface;
//定义接口 ISwim
public interface ISwim {
public abstract void swim();
}
(5)Student 类的子类 SwimStudent 类
package abstractvsinterface;
//SwimStudent 类 继承 Student 类
//并 实现 会游泳的接口 ISwim
public class SwimStudent extends Student implements ISwim {
public SwimStudent() {
}
public SwimStudent(String name) {
super(name);
}
//实现接口里的抽象方法
public void swim() {
System.out.println("会游泳的学生");
}
}
(6)Teacher 类的子类 SwimTeacher 类
package abstractvsinterface;
//SwimTeacher 类 继承 Teacher 类
//并 实现 会游泳的接口 ISwim
public class SwimTeacher extends Teacher implements ISwim {
public SwimTeacher() {
}
public SwimTeacher(String name) {
super(name);
}
//实现接口里的抽象方法
public void swim() {
System.out.println("会游泳的老师");
}
}
(7)测试类 Test03 类
package abstractvsinterface;
//测试抽象类和接口
public class Test03 {
public static void main(String[] args) {
//测试学生
Person s1 = new Student(); //抽象类的实例化,向上转型
s1.setName("学生1");
s1.sleep();
System.out.println("-------------------");
SwimStudent s2 = new SwimStudent();
s2.setName("学生2");
s2.sleep();
s2.swim(); //由于实现了接口ISwim,因此可以调用swim()方法
System.out.println("-------------------");
//测试老师
Person t1 = new Teacher(); //抽象类的实例化,向上转型
t1.setName("老师1");
t1.sleep();
System.out.println("-------------------");
SwimTeacher t2 = new SwimTeacher();
t2.setName("老师2");
t2.sleep();
t2.swim(); //由于实现了接口ISwim,因此可以调用swim()方法
}
}
(8)运行结果
学生1回宿舍睡觉! ------------------- 学生2回宿舍睡觉! 学生2是会游泳的学生 ------------------- 老师1回学校公寓睡觉! ------------------- 老师2回学校公寓睡觉! 老师2是会游泳的老师3. 抽象类和接口的使用场景 3.1 抽象类的使用场景
- 父类只知道其子类应该包含怎样的方法,不能准确知道这些子类如何实现这些方法的情况下,使用抽象类。
- 从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,这样可以避免子类设计的随意性。
- 一般来说,实现类和它的抽象类之间具有 “is-a” 的关系,但是如果我们想达到同样的目的,但是又不存在这种关系时,使用接口。
- 由于 Java 中单继承的特性,导致一个类只能继承一个类,但是可以实现一个或多个接口,如果想实现多重继承,此时可以使用接口。即通过实现多个接口可以弥补 Java 单继承的不足。



