增加了较复杂的接口和抽象类的例子

This commit is contained in:
2024-04-08 21:28:16 +08:00
parent 4cc8cca557
commit 4fad7a3eb9
2 changed files with 542 additions and 3 deletions
+162 -3
View File
@@ -546,7 +546,7 @@ edible.howToEat();
## 3. 接口的使用
### 3.1. Comparable接口(解)
### 3.1. Comparable接口(解)
首先来回忆一下在数组那一章学习到的排序函数:
@@ -620,7 +620,7 @@ public class SortRectangles {
> 挑战:如果圆形和方形面积可以参与比较,是不是数组中可以存在圆形和方形的对象,而且也可以排序?答案是肯定的。可以尝试对圆形和方形的混合数组进行排序。提示:最好不要在 圆形和方形的类上实现 Comparable 接口,而应该在其父类实现 Comparable 接口。想一想为什么?
## 4. 接口和抽象类
## 4. 接口和抽象类(了解)
> In an interface, the data must be constants; an abstract class can have all types of data. Each method in an interface has only a signature without implementation; an abstract class can have concrete methods.
>
@@ -637,6 +637,165 @@ public class SortRectangles {
1. 实线箭头表示类的扩展;虚线街头表示接口的扩展方向;
2. 所有类都有一个共同的超类 Object,但是接口没有共同的**超接口**。
## 本章重点
### 4.1. 补充说明(了解)
Java 在类的继承的关系上是单继承方式,也就是说,在定义一个类的时候,有且只能有一个父类(C++是多继承,可以有多个父类)。但是在接口实现上可能有多个。一般来说,接口用来统一某些能力,但是这种能力很难以类属的方式来抽象。
### 4.2. 接口与类属关系
如下图:数码产品的分类。圆形的是耳机接口,半圆是`USB`接口(接口中的数字代表是2.0还是3.0接口标准)。
![Alt text](img/%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E.drawio.svg)
我们看到不论是耳机接口还是`USB`接口都很难抽象到父类,这两个能力(特性)是和类属无关的,但是又广泛存在于不同的数码产品中。同时我们注意到,`USB3``USB2`的升级,也就是说`USB3``USB2`扩展而来。接下来我们`UML`的方式来描述:
#### 4.2.1. 类属关系:
```mermaid
classDiagram
DigitalDevice <|-- Speaker
DigitalDevice <|-- Mobile
DigitalDevice <|-- Laptop
Speaker <|-- SpeakerA
Speaker <|-- SpeakerB
Mobile <|-- MobileX
Mobile <|-- MobileY
Laptop <|-- LaptopA
Laptop <|-- LaptopB
class DigitalDevice{
<<Abstract>>
+ boolean status
+ on()
+ off()
}
class Speaker{
<<Abstract>>
+speak()*
}
class Mobile{
<<Abstract>>
+phoneCall(String number)*
}
class Laptop{
<<Abstract>>
+runProgram(String file)*
}
```
我们把相同的能力尽量向上级抽象,更便于我们使用多态的机制。
抽象类:`DigitalDevice`
1. 所有的数码设备都有状态`status`,要么开机,要么关机;
2. 所有的数码设备都有开,和关的功能,因此用两个函数`on()``off()`描述;
因此可以把上述的变量和函数抽象到`DigitalDevice`这样,所有的子类都具备上述的能力(注意:函数可能被覆盖)。
对于特定的子类型:`Speaker``Mobile``Laptop`都有自己特有的能力:
1. Speaker`speak()` 播放声音;
2. Mobile`phoneCall(String number)`打电话;
3. Laptop`runProgram(String file)`运行程序。
上述三个类,连同`DigitalDevice`都是抽象类。真正可以实例化的类是:
1. `SpeakerA`
2. `SpeakerB`
3. `MobileX`
4. `MobileY`
5. `LaptopA`
6. `LaptopB`
#### 4.2.2. 接口描述
`Line35``3.5mm` 的耳机接口。
```mermaid
classDiagram
Usb2 <|-- Usb3
class Line35{
<<Interface>>
+lineOn()*
+lineOff()*
}
class Usb2{
<<Interface>>
byte[] read()*
write(byte[] data)*
}
class Usb3{
<<Interface>>
negotiationSpeed()*
}
Line35 <|.. SpeakerA
Usb2 <|.. SpeakerA
Usb2 <|.. MobileX
Line35 <|.. MobileX
Line35 <|.. LaptopB
Usb3 <|.. MobileY
Usb3 <|.. LaptopA
Usb3 <|.. LaptopB
Line35 <|.. SpeakerB
```
再看看接口的实现关系:
1. Usb3 的父接口是 Usb2
2. 最终不同的数码产品实现的不同的接口。
### 4.3. Java 代码
```java
Object speakerA = new SpeakerA();
Object speakerB = new SpeakerB();
Object mobileX = new MobileX();
Object mobileY = new MobileY();
Object laptopA = new LaptopA();
Object laptopB = new LaptopB();
System.out.println(laptopB instanceof DigitDevice); // true
System.out.println(laptopB instanceof Speaker); // false
System.out.println(laptopB instanceof Laptop); // true
System.out.println(laptopB instanceof LaptopB); // true
Usb2 usb2 = (Usb2)laptopB; // 合法,因为USB3是USB2的子接口,具备USB2的所有能力
usb2.read(); // 合法
usb2.negotiationSpeed(); // 编译错误,没有这个函数。Java认为 usb2 的引用变量类型是 USB2 没有该函数;
Usb3 usb3 = (Usb3)laptopB; // 合法,实现了USB3的接口
usb3.negotiationSpeed(); // 合法
Line35 line35 = (Line35)laptopB; // 合法,实现了Line35的接口
line35.lineOn(); // 合法
Laptop laptop = (Laptop)laptopB; // 合法,是Laptop的子类型
laptop.runProgram("C:/a.exe"); // 合法
laptop.on(); // 合法,因为是DigitalDevice的子类型,具有`on()`和`off`的函数;
```
顺着继承的关系和接口的实现关系来阅读上述的代码。
## 5. 本章重点
除特别标注,其他都是重点,需要掌握。