Java 面向对象 · 交互课程

接口与多态

接口与多态

目标:掌握多态的三条件与动态绑定;理解接口的本质是「制定标准/契约」;会声明 interface、用 implements 实现(含多接口);会用接口变量做回调、用接口类型作方法参数——这正是接口实现多态的方式;能辨析接口与抽象类的取舍。

一、多态:同一消息,不同行为

多态(Polymorphism) = 「多种形态」:同一条消息(方法调用),发给不同对象,产生不同的行为。

Animal a = new Dog();   // 向上转型:父类引用指向子类对象
a.speak();              // 运行期执行 Dog 的 speak(),而不是 Animal 的

动手:看多态分派

交互实验:多态与动态绑定(PolymorphismDemo)

选一个「引用 = 对象」场景,点调用按钮:编译期看引用类型有没有这个方法,运行期按实际对象类型执行对应版本。

编译期(看引用类型)Animal 中声明了 speak() → ✅ 通过
运行期(看实际对象)实际是 Dog → 执行 Dog.speak()

// 点按钮执行调用

多态三条件:① 有继承;② 子类重写了方法(签名相同);③ 父类引用指向子类对象(向上转型)。 三者齐备,同一句 speak() 才能产生不同行为。

多态的三个条件

  1. 继承(或实现):子类与父类(实现类与接口)存在 is-a 关系;
  2. 方法重写:子类重写了父类的同名同参方法;
  3. 向上转型:用父类/接口类型的引用指向子类对象。

注意:重载(Overload)与多态分派无关——重载是同一个类里同名不同参,编译期就确定了调哪个。

二、接口 = 制定标准

万能充电器、主板的 USB/HDMI 口、墙上的插座——它们的共同点:制定统一标准,让「使用者」与「被使用者」按标准对接,彼此不必关心对方内部实现。

Java 的 interface 正是如此:调用方只依赖接口(标准),不依赖具体类——解耦、可替换、可扩展。

三、声明与实现

public interface IUsb {
    void connect();      // 默认 public abstract
    void disconnect();
}

public class Phone implements IUsb {
    public void connect()    { System.out.println("手机通过USB连接"); }
    public void disconnect() { System.out.println("手机断开USB"); }
}

规则要点:

四、用接口实现多态:回调与接口参数

继承是多态的一条路,接口是另一条——不相关的类只要实现了同一接口,就能被统一对待:

IUsb dev = new Phone();   // 接口变量引用实现类对象(向上转型到接口)
dev.connect();            // 实际执行 Phone 的 connect()

void use(IUsb dev) {      // 形参是接口类型:手机、U盘、相机都能传入
    dev.connect();
}

交互实验:回调注册器(CallbackRegistry)

接口 IUsb { connect(); } 有三个实现类。 把监听器注册到某个事件下,再触发该事件——每个已注册的接口变量都会调用其实际对象的 connect()(动态分派)。

① 事件

② 注册监听器(点选)

③ 触发事件

触发后这里显示调用序列。

关键:方法里拿到的形参是接口类型,运行时按实际对象决定调哪个实现——手机、U盘、相机毫无血缘,却能共享同一套调用代码。

五、接口 vs 抽象类

交互实验:接口 vs 抽象类(InterfaceVsAbstract)

点任意一行展开说明。

接口 interface抽象类 abstract class

只有必须共享已实现的成员/方法时才考虑抽象类;否则优先用接口——更低耦合、更好扩展。

思考题

  1. 写出多态的三个条件,并说明为什么「重载」不算在内。
  2. 用「万能充电器 / 主板接口」类比,说明接口「制定标准」的作用。
  3. Animal a = new Dog() 与 IUsb dev = new Phone() 两种多态写法各适用于什么场景?

学习小测验

学习小测验

Q1

Animal a = new Dog(); 后调用 a.speak()(Dog 已重写),执行的是?

Q2

实现多态的必要条件不包括( )

Q3

Java 中用于定义接口的关键字是( )

Q4

接口中的方法默认是( )的

Q5

类实现多个接口的写法是( )

Q6

实现接口时漏写 public 会怎样?

Q7

IUsb dev = new Phone(); 后 dev.connect() 执行的是?

Q8

关于接口与抽象类,正确的是( )