|
|
@@ -703,9 +703,260 @@ public class Example {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-## 七、随堂练习要点
|
|
|
+## 七、接口(Interface)
|
|
|
|
|
|
-**练习目标**:理解抽象类的定义和使用
|
|
|
+### 1. 接口的引出——解决单继承的局限性
|
|
|
+
|
|
|
+**文件**:`Demo05.java`
|
|
|
+
|
|
|
+Java 中的继承是 **单继承**,一个子类只能直接继承一个父类。这种方式逻辑清晰,但扩展性较低。
|
|
|
+
|
|
|
+```
|
|
|
+学生类 extends 人类
|
|
|
+
|
|
|
+鹦鹉 extends 鸟类
|
|
|
+
|
|
|
+鸟人 extends ? ← 既有人类的特征,又有鸟类的飞行能力,单继承无法解决
|
|
|
+```
|
|
|
+
|
|
|
+为了解决单继承带来的局限性,Java 提出了 **接口** 的概念。
|
|
|
+
|
|
|
+**接口(Interface)** 是一种公共规范标准,只要符合这个规范标准,大家都可以通用。
|
|
|
+
|
|
|
+```
|
|
|
+鸟人 extends 人类 实现 飞行接口 ← 继承父类 + 实现接口,两者互补
|
|
|
+```
|
|
|
+
|
|
|
+**接口存在的意义**:
|
|
|
+- **定义规范** — 规定实现类必须遵循的行为标准
|
|
|
+- **功能拓展** — 在继承父类的基础上,额外扩展其他能力
|
|
|
+
|
|
|
+> 俗话说的好:「**单继承 + 多实现**」——一个类只能继承一个父类,但可以同时实现多个接口。
|
|
|
+
|
|
|
+### 2. 接口的定义
|
|
|
+
|
|
|
+**文件**:`Demo05.java`、`MyInterface.java`
|
|
|
+
|
|
|
+接口的关键字是 `interface`。接口也是一种引用数据类型(或者说接口也是一种类)。
|
|
|
+
|
|
|
+```java
|
|
|
+public interface 接口名 {
|
|
|
+ // 成员
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**接口的成员特点**:
|
|
|
+
|
|
|
+| 成员类型 | 默认修饰符 | 说明 |
|
|
|
+|---------|-----------|------|
|
|
|
+| **变量** | `public static final` | 接口中定义的变量都是 **公开的静态常量** |
|
|
|
+| **方法** | `public abstract` | 接口中定义的方法都是 **公开的抽象方法** |
|
|
|
+
|
|
|
+```java
|
|
|
+public interface MyInterface {
|
|
|
+ // 变量——默认使用 public static final
|
|
|
+ public static final String name = "张三";
|
|
|
+
|
|
|
+ // 方法——默认使用 public abstract
|
|
|
+ public abstract void method();
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> **注意**:接口和抽象类一样 **不能实例化**(不能创建对象),且接口 **没有构造方法**。
|
|
|
+
|
|
|
+### 3. 接口的实现
|
|
|
+
|
|
|
+**文件**:`Demo05.java`
|
|
|
+
|
|
|
+子类继承接口称为「**实现** 接口」,使用关键字 `implements`。
|
|
|
+
|
|
|
+```java
|
|
|
+public class 实现类 implements 接口 {
|
|
|
+ // 必须重写(实现)接口中所有的抽象方法
|
|
|
+}
|
|
|
+
|
|
|
+// 类可以同时继承父类 + 实现接口
|
|
|
+public class 子类 extends 父类 implements 接口1, 接口2, ... {
|
|
|
+ // 必须重写所有接口中的抽象方法
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**接口的子类(实现类)规则**:
|
|
|
+- 要么重写(实现)接口中 **所有** 的抽象方法
|
|
|
+- 要么子类也是一个 **抽象类**
|
|
|
+
|
|
|
+**接口与抽象类的对比**:
|
|
|
+
|
|
|
+| 对比维度 | 抽象类 | 接口 |
|
|
|
+|---------|-------|------|
|
|
|
+| **关键字** | `abstract class` | `interface` |
|
|
|
+| **构造方法** | 可以有 | 不能有 |
|
|
|
+| **成员变量** | 可以是任意类型 | 只能是 `public static final` 常量 |
|
|
|
+| **成员方法** | 可以有抽象/非抽象方法 | 只能是 `public abstract` 抽象方法 |
|
|
|
+| **子类方式** | `extends`(继承) | `implements`(实现) |
|
|
|
+| **单/多** | 单继承 | 可同时实现多个接口 |
|
|
|
+
|
|
|
+### 4. USB 接口标准示例
|
|
|
+
|
|
|
+#### 4.1 定义 USB 接口标准
|
|
|
+
|
|
|
+**文件**:`Usb.java`
|
|
|
+
|
|
|
+```java
|
|
|
+package course;
|
|
|
+
|
|
|
+public interface Usb {
|
|
|
+ void startUsb(); // 默认 public abstract
|
|
|
+ void useUsb(); // 默认 public abstract
|
|
|
+ void stopUsb(); // 默认 public abstract
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+USB 接口定义了一个规范标准:任何 USB 设备都必须具备「启动 → 使用 → 关闭」三个行为。
|
|
|
+
|
|
|
+#### 4.2 父类 Mouse
|
|
|
+
|
|
|
+**文件**:`Mouse.java`
|
|
|
+
|
|
|
+```java
|
|
|
+public class Mouse {
|
|
|
+ private String brand;
|
|
|
+ private double price;
|
|
|
+
|
|
|
+ public Mouse(String brand, double price) {
|
|
|
+ this.brand = brand;
|
|
|
+ this.price = price;
|
|
|
+ }
|
|
|
+ // getter/setter 省略...
|
|
|
+ public void showInfo() {
|
|
|
+ System.out.println("品牌:" + brand + ",价格:" + price);
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 4.3 实现类 LogiMouse(罗技鼠标)
|
|
|
+
|
|
|
+**文件**:`LogiMouse.java`
|
|
|
+
|
|
|
+```java
|
|
|
+// 继承父类 Mouse + 实现 Usb 接口
|
|
|
+public class LogiMouse extends Mouse implements Usb {
|
|
|
+
|
|
|
+ public LogiMouse(String brand, double price) {
|
|
|
+ super(brand, price);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void startUsb() {
|
|
|
+ System.out.println("罗技鼠标启动");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void useUsb() {
|
|
|
+ System.out.println("罗技鼠标使用");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void stopUsb() {
|
|
|
+ System.out.println("罗技鼠标关闭");
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 4.4 实现类 ROGMouse(ROG 鼠标)
|
|
|
+
|
|
|
+**文件**:`ROGMouse.java`
|
|
|
+
|
|
|
+```java
|
|
|
+public class ROGMouse extends Mouse implements Usb {
|
|
|
+ public ROGMouse(String brand, double price) {
|
|
|
+ super(brand, price);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void startUsb() {
|
|
|
+ System.out.println("ROG鼠标启动");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void useUsb() {
|
|
|
+ System.out.println("ROG鼠标使用");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void stopUsb() {
|
|
|
+ System.out.println("ROG鼠标关闭");
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+#### 4.5 测试类 Test04
|
|
|
+
|
|
|
+**文件**:`Test04.java`
|
|
|
+
|
|
|
+```java
|
|
|
+public class Test04 {
|
|
|
+ public static void main(String[] args) {
|
|
|
+ LogiMouse lm = new LogiMouse("罗技", 13.6);
|
|
|
+ lm.showInfo(); // 调用父类 Mouse 的方法
|
|
|
+ lm.startUsb(); // 实现 Usb 接口的抽象方法
|
|
|
+ lm.useUsb(); // 实现 Usb 接口的抽象方法
|
|
|
+ lm.stopUsb(); // 实现 Usb 接口的抽象方法
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**预期输出**:
|
|
|
+```
|
|
|
+品牌:罗技,价格:13.6
|
|
|
+罗技鼠标启动
|
|
|
+罗技鼠标使用
|
|
|
+罗技鼠标关闭
|
|
|
+```
|
|
|
+
|
|
|
+### 5. 继承与接口的实现关系图
|
|
|
+
|
|
|
+```
|
|
|
+ ┌──────────┐ ┌──────────┐
|
|
|
+ │ Mouse │ │ Usb │
|
|
|
+ │ (父类) │ │ (接口) │
|
|
|
+ └────┬─────┘ └────┬─────┘
|
|
|
+ │ extends │ implements
|
|
|
+ ┌────────┴──────────┐ │
|
|
|
+ │ │ │
|
|
|
+┌───┴────────┐ ┌──────┴─────┐ │
|
|
|
+│ LogiMouse │ │ ROGMouse ├────┘
|
|
|
+│ extends │ │ extends │
|
|
|
+│ Mouse │ │ Mouse │
|
|
|
+│ implements │ │ implements│
|
|
|
+│ Usb │ │ Usb │
|
|
|
+└────────────┘ └────────────┘
|
|
|
+```
|
|
|
+
|
|
|
+### 6. 接口的补充特性
|
|
|
+
|
|
|
+**文件**:`Demo05.java`
|
|
|
+
|
|
|
+- **类与接口**:一个类虽然只能继承一个父类,但是可以同时 **实现多个接口**
|
|
|
+- **接口与接口**:接口之间可以 **多继承**(一个子接口可以继承多个父接口)
|
|
|
+
|
|
|
+```java
|
|
|
+// 类实现多个接口
|
|
|
+public class MyClass implements InterfaceA, InterfaceB, InterfaceC {
|
|
|
+ // 必须重写所有接口中的抽象方法
|
|
|
+}
|
|
|
+
|
|
|
+// 接口继承多个接口
|
|
|
+public interface SubInterface extends InterfaceA, InterfaceB {
|
|
|
+ // 子接口继承多个父接口的方法
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 八、随堂练习要点
|
|
|
+
|
|
|
+**练习目标**:理解抽象类、接口、代码块的基本使用
|
|
|
|
|
|
1. **定义抽象父类**:使用 `public abstract class` 声明,定义抽象方法时不要写方法体
|
|
|
2. **实现具体子类**:使用 `extends` 继承抽象类,使用 `@Override` 重写所有抽象方法
|
|
|
@@ -713,7 +964,7 @@ public class Example {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 八、面试常见问题
|
|
|
+## 九、面试常见问题
|
|
|
|
|
|
**Q1:抽象类能不能被实例化?**
|
|
|
> 不能。抽象类不能直接 `new` 创建对象。
|
|
|
@@ -748,11 +999,24 @@ public class Example {
|
|
|
**Q11:构造代码块有什么作用?**
|
|
|
> 构造代码块可以把多个构造方法中共同的代码提取出来,避免重复。每次创建对象时,构造代码块会在构造方法之前自动执行,无论调用的是哪个重载的构造方法。
|
|
|
|
|
|
+**Q12:接口和抽象类有什么区别?**
|
|
|
+> ① 关键字不同:抽象类是 `abstract class`,接口是 `interface`;② 构造方法:抽象类可以有,接口不能有;③ 成员变量:抽象类可以是任意类型,接口只能是 `public static final` 常量;④ 成员方法:抽象类可以有抽象/非抽象方法,接口只能是 `public abstract` 抽象方法;⑤ 子类方式:抽象类用 `extends` 继承,接口用 `implements` 实现;⑥ 单/多:抽象类是单继承,接口可以同时实现多个。
|
|
|
+
|
|
|
+**Q13:一个类可以同时继承一个父类并实现多个接口吗?**
|
|
|
+> 可以。Java 中的类虽然只能单继承(一个父类),但可以同时实现多个接口。格式:`public class 子类 extends 父类 implements 接口1, 接口2 { ... }`。
|
|
|
+
|
|
|
+**Q14:接口中的变量默认使用什么修饰符?方法呢?**
|
|
|
+> 接口中的变量默认使用 `public static final` 修饰(公开的静态常量),方法默认使用 `public abstract` 修饰(公开的抽象方法)。
|
|
|
+
|
|
|
+**Q15:接口为什么不能实例化?接口有构造方法吗?**
|
|
|
+> 接口没有构造方法,因此不能实例化(不能创建对象)。接口是一种规范标准,需要通过实现类来提供具体的功能实现。
|
|
|
+
|
|
|
---
|
|
|
|
|
|
-## 九、拓展阅读
|
|
|
+## 十、拓展阅读
|
|
|
|
|
|
- [Java 抽象类(Oracle 官方文档)](https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html)
|
|
|
+- [Java 接口(Oracle 官方文档)](https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html)
|
|
|
- [Java 代码块初始化(Oracle 官方文档)](https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html)
|
|
|
-- 抽象类 vs 接口(Interface)的区别(将在后续课程中讲解)
|
|
|
+- 抽象类 vs 接口(Interface)的区别对比
|
|
|
- 模板方法设计模式(Template Method Pattern)—— 抽象类的经典应用场景
|