mirror of
https://gitee.com/gaohongy/Java-Book.git
synced 2026-07-16 10:33:49 +00:00
增加了较复杂的接口和抽象类的例子
This commit is contained in:
+162
-3
@@ -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接口标准)。
|
||||
|
||||

|
||||
|
||||
我们看到不论是耳机接口还是`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. 本章重点
|
||||
|
||||
除特别标注,其他都是重点,需要掌握。
|
||||
Reference in New Issue
Block a user