如何判断应该设计类、子类、抽象类或接口?
- 1、设计新类
- 1.1 原则
- 1.2 解释
- 1.3 示例
- 2、设计子类
- 2.1 原则
- 2.2 解释
- 2.3 示例
- 3、设计抽象类额
- 3.1 原则
- 3.2 解释
- 3.3 示例
- 4、设计接口
- 4.1 原则
- 4.2 解释
- 4.3 示例
来源:《Head First Java》第二版:227 页
1、设计新类
1.1 原则
如果新的类无法对其他的类通过 IS-A 测试时,就设计不继承其他类的类;
1.2 解释
- IS-A 测试:如果新的类不能被合理地认为是另一个类的一种类型,则不应该使用继承。
- 不使用继承:当新的类与现有类之间不存在 IS-A 关系时,应该避免继承。
1.3 示例
假设我们有两个类 Vehicle
和 Book
,它们之间没有任何继承关系。
public class Vehicle {private String model;public void drive() {System.out.println("Driving the vehicle.");}
}public class Book {private String title;public void read() {System.out.println("Reading the book.");}
}
在这个例子中,Vehicle
类代表汽车或其他交通工具,而 Book
类代表书籍。很明显,一本书不是一种交通工具,因此 Book
类不应该继承 Vehicle
类。相反,它们是完全独立的类。
2、设计子类
2.1 原则
只有在需要某类的特殊化版本时,以覆盖或增加新的方法来继承现有的类;
2.2 解释
- 特殊化版本:当新的类需要扩展或修改现有类的功能时,可以使用继承。
- 覆盖或增加新方法:子类可以通过重写父类的方法或添加新方法来扩展功能。
2.3 示例
假设我们有一个 Vehicle
类,我们想要创建一个 Car
类,它是 Vehicle
类的一个特殊版本。
public abstract class Vehicle {private String model;public abstract void startEngine();public void drive() {System.out.println("Driving the vehicle.");}
}public class Car extends Vehicle {private String color;public Car(String model, String color) {this.model = model;this.color = color;}@Overridepublic void startEngine() {System.out.println("Starting the car's engine.");}public void setColor(String color) {this.color = color;}public String getColor() {return color;}
}
在这个例子中,Car
类继承了 Vehicle
类,并且实现了抽象方法 startEngine()
。此外,Car
类还添加了新的方法 setColor()
和 getColor()
来设置和获取颜色。
3、设计抽象类额
3.1 原则
当你需要定一个一群子类的模板,又不想让程序员初始化此模板时,设计出抽象的类给它们用;
3.2 解释
- 模板:抽象类定义了一组方法,但不允许直接实例化。
- 不允许初始化:抽象类不能被直接实例化,只能被继承。
3.3 示例
假设我们有一个 Shape
抽象类,它定义了 area()
和 perimeter()
方法。
public abstract class Shape {public abstract double area();public abstract double perimeter();
}public class Circle extends Shape {private double radius;public Circle(double radius) {this.radius = radius;}@Overridepublic double area() {return Math.PI * radius * radius;}@Overridepublic double perimeter() {return 2 * Math.PI * radius;}
}
在这个例子中,Shape
是一个抽象类,它定义了 area()
和 perimeter()
方法。Circle
类继承了 Shape
类,并实现了这些方法。由于 Shape
是抽象的,我们不能直接创建 Shape
类的实例。
4、设计接口
4.1 原则
如果想定义出类可以扮演的角色,使用接口。
4.2 解释
- 角色:接口定义了一组方法,没有提供任何实现。
- 实现多个接口:一个类可以实现多个接口,从而扮演多种角色。
4.3 示例
假设我们有一个 Flyable
接口,它定义了飞行能力,还有一个 Swimmable
接口,它定义了游泳能力。
public interface Flyable {void fly();
}public interface Swimmable {void swim();
}public class Duck implements Flyable, Swimmable {@Overridepublic void fly() {System.out.println("Duck is flying.");}@Overridepublic void swim() {System.out.println("Duck is swimming.");}
}
在这个例子中,Duck
类实现了 Flyable
和 Swimmable
接口,这意味着它可以同时扮演会飞和会游泳的角色。