本章目标
- 深入理解面向对象的核心概念
- 掌握类与对象的关系和设计原则
- 理解继承、封装、多态的本质和应用
- 学会正确使用接口和抽象类
- 掌握对象间关系的设计和实现
2.1 面向对象核心概念
2.1.1 类与对象
类(Class)是对象的模板或蓝图,定义了对象的属性和行为。 对象(Object)是类的实例,具有具体的属性值和可执行的行为。
// 类的定义
public class Car {
// 属性(状态)
private String brand;
private String model;
private int year;
private double speed;
private boolean isRunning;
// 构造方法
public Car(String brand, String model, int year) {
this.brand = brand;
this.model = model;
this.year = year;
this.speed = 0.0;
this.isRunning = false;
}
// 行为(方法)
public void start() {
if (!isRunning) {
isRunning = true;
System.out.println(brand + " " + model + " started.");
}
}
public void stop() {
if (isRunning) {
isRunning = false;
speed = 0.0;
System.out.println(brand + " " + model + " stopped.");
}
}
public void accelerate(double increment) {
if (isRunning) {
speed += increment;
System.out.println("Speed: " + speed + " km/h");
} else {
System.out.println("Car is not running. Start the car first.");
}
}
// Getter和Setter方法
public String getBrand() { return brand; }
public String getModel() { return model; }
public int getYear() { return year; }
public double getSpeed() { return speed; }
public boolean isRunning() { return isRunning; }
}
// 对象的创建和使用
public class CarDemo {
public static void main(String[] args) {
// 创建对象
Car myCar = new Car("Toyota", "Camry", 2023);
Car friendCar = new Car("Honda", "Civic", 2022);
// 使用对象
myCar.start();
myCar.accelerate(50);
myCar.accelerate(30);
myCar.stop();
friendCar.start();
friendCar.accelerate(60);
System.out.println(friendCar.getBrand() + " speed: " + friendCar.getSpeed());
}
}
2.1.2 类的设计原则
1. 高内聚(High Cohesion)
类的内部元素应该紧密相关,共同完成一个明确的功能。
# 低内聚的例子(不好的设计)
class UserManager:
def __init__(self):
self.users = []
self.email_service = EmailService()
self.file_system = FileSystem()
def add_user(self, user):
self.users.append(user)
def send_email(self, to, subject, body): # 与用户管理无关
self.email_service.send(to, subject, body)
def save_file(self, filename, content): # 与用户管理无关
self.file_system.save(filename, content)
def calculate_tax(self, income): # 与用户管理无关
return income * 0.2
# 高内聚的重构
class UserManager:
def __init__(self):
self.users = []
def add_user(self, user):
if self.validate_user(user):
self.users.append(user)
return True
return False
def remove_user(self, user_id):
self.users = [u for u in self.users if u.id != user_id]
def find_user(self, user_id):
return next((u for u in self.users if u.id == user_id), None)
def validate_user(self, user):
# 用户验证逻辑
return user.email and user.name
def get_active_users(self):
return [u for u in self.users if u.is_active]
class EmailService:
def send(self, to, subject, body):
# 邮件发送逻辑
pass
class TaxCalculator:
def calculate_tax(self, income):
return income * 0.2
2. 低耦合(Low Coupling)
类之间的依赖关系应该尽可能少,减少相互影响。
// 高耦合的例子(不好的设计)
class DatabaseConnection {
public:
void connect() {
std::cout << "Connecting to MySQL database..." << std::endl;
}
void disconnect() {
std::cout << "Disconnecting from MySQL database..." << std::endl;
}
void executeQuery(const std::string& query) {
std::cout << "Executing: " << query << std::endl;
}
};
class UserService {
private:
DatabaseConnection db; // 紧耦合到具体的数据库实现
public:
void createUser(const std::string& name, const std::string& email) {
db.connect();
std::string query = "INSERT INTO users (name, email) VALUES ('" +
name + "', '" + email + "')";
db.executeQuery(query);
db.disconnect();
}
};
// 低耦合的重构
#include <memory>
class DatabaseInterface {
public:
virtual ~DatabaseInterface() = default;
virtual void connect() = 0;
virtual void disconnect() = 0;
virtual void executeQuery(const std::string& query) = 0;
};
class MySQLDatabase : public DatabaseInterface {
public:
void connect() override {
std::cout << "Connecting to MySQL database..." << std::endl;
}
void disconnect() override {
std::cout << "Disconnecting from MySQL database..." << std::endl;
}
void executeQuery(const std::string& query) override {
std::cout << "MySQL executing: " << query << std::endl;
}
};
class PostgreSQLDatabase : public DatabaseInterface {
public:
void connect() override {
std::cout << "Connecting to PostgreSQL database..." << std::endl;
}
void disconnect() override {
std::cout << "Disconnecting from PostgreSQL database..." << std::endl;
}
void executeQuery(const std::string& query) override {
std::cout << "PostgreSQL executing: " << query << std::endl;
}
};
class UserService {
private:
std::unique_ptr<DatabaseInterface> db;
public:
UserService(std::unique_ptr<DatabaseInterface> database)
: db(std::move(database)) {}
void createUser(const std::string& name, const std::string& email) {
db->connect();
std::string query = "INSERT INTO users (name, email) VALUES ('" +
name + "', '" + email + "')";
db->executeQuery(query);
db->disconnect();
}
};
// 使用示例
int main() {
// 可以轻松切换数据库实现
auto mysqlService = std::make_unique<UserService>(
std::make_unique<MySQLDatabase>()
);
auto postgresService = std::make_unique<UserService>(
std::make_unique<PostgreSQLDatabase>()
);
mysqlService->createUser("John", "john@example.com");
postgresService->createUser("Jane", "jane@example.com");
return 0;
}
2.2 封装(Encapsulation)
2.2.1 封装的概念
封装是将数据和操作数据的方法绑定在一起,并隐藏对象的内部实现细节,只暴露必要的接口。
2.2.2 访问控制
public class BankAccount {
// 私有属性,外部无法直接访问
private String accountNumber;
private double balance;
private String ownerName;
private boolean isActive;
// 构造方法
public BankAccount(String accountNumber, String ownerName, double initialBalance) {
this.accountNumber = accountNumber;
this.ownerName = ownerName;
this.balance = initialBalance;
this.isActive = true;
}
// 公共方法,提供受控的访问
public boolean deposit(double amount) {
if (!isActive) {
System.out.println("Account is inactive");
return false;
}
if (amount <= 0) {
System.out.println("Deposit amount must be positive");
return false;
}
balance += amount;
System.out.println("Deposited: $" + amount + ", New balance: $" + balance);
return true;
}
public boolean withdraw(double amount) {
if (!isActive) {
System.out.println("Account is inactive");
return false;
}
if (amount <= 0) {
System.out.println("Withdrawal amount must be positive");
return false;
}
if (amount > balance) {
System.out.println("Insufficient funds");
return false;
}
balance -= amount;
System.out.println("Withdrawn: $" + amount + ", New balance: $" + balance);
return true;
}
// 只读访问器
public double getBalance() {
return isActive ? balance : 0;
}
public String getAccountNumber() {
return accountNumber;
}
public String getOwnerName() {
return ownerName;
}
public boolean isActive() {
return isActive;
}
// 受控的状态修改
public void deactivateAccount() {
isActive = false;
System.out.println("Account deactivated");
}
public void activateAccount() {
isActive = true;
System.out.println("Account activated");
}
// 私有辅助方法
private boolean validateAmount(double amount) {
return amount > 0;
}
private void logTransaction(String type, double amount) {
System.out.println("Transaction: " + type + ", Amount: $" + amount +
", Time: " + java.time.LocalDateTime.now());
}
}
2.2.3 属性封装的最佳实践
class Temperature:
def __init__(self, celsius=0):
self._celsius = celsius # 受保护的属性
@property
def celsius(self):
"""获取摄氏温度"""
return self._celsius
@celsius.setter
def celsius(self, value):
"""设置摄氏温度,包含验证逻辑"""
if value < -273.15:
raise ValueError("Temperature cannot be below absolute zero")
self._celsius = value
@property
def fahrenheit(self):
"""获取华氏温度"""
return (self._celsius * 9/5) + 32
@fahrenheit.setter
def fahrenheit(self, value):
"""通过华氏温度设置摄氏温度"""
celsius_value = (value - 32) * 5/9
self.celsius = celsius_value # 使用celsius的setter进行验证
@property
def kelvin(self):
"""获取开尔文温度"""
return self._celsius + 273.15
@kelvin.setter
def kelvin(self, value):
"""通过开尔文温度设置摄氏温度"""
if value < 0:
raise ValueError("Kelvin temperature cannot be negative")
self._celsius = value - 273.15
def __str__(self):
return f"{self._celsius}°C ({self.fahrenheit}°F, {self.kelvin}K)"
# 使用示例
temp = Temperature(25)
print(temp) # 25°C (77.0°F, 298.15K)
temp.fahrenheit = 100
print(temp) # 37.77777777777778°C (100.0°F, 310.92777777777775K)
temp.kelvin = 300
print(temp) # 26.850000000000023°C (80.33000000000004°F, 300.0K)
# 尝试设置无效值
try:
temp.celsius = -300 # 会抛出异常
except ValueError as e:
print(f"Error: {e}")
2.3 继承(Inheritance)
2.3.1 继承的基本概念
继承允许一个类(子类)获得另一个类(父类)的属性和方法,实现代码复用和层次化设计。
// 基类(父类)
public abstract class Animal {
protected String name;
protected int age;
protected double weight;
public Animal(String name, int age, double weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
// 具体方法
public void eat(String food) {
System.out.println(name + " is eating " + food);
weight += 0.1; // 假设每次进食增加0.1kg
}
public void sleep(int hours) {
System.out.println(name + " is sleeping for " + hours + " hours");
}
// 抽象方法,子类必须实现
public abstract void makeSound();
public abstract void move();
// Getter方法
public String getName() { return name; }
public int getAge() { return age; }
public double getWeight() { return weight; }
@Override
public String toString() {
return getClass().getSimpleName() + "{name='" + name + "', age=" + age + ", weight=" + weight + "}";
}
}
// 派生类(子类)
public class Dog extends Animal {
private String breed;
private boolean isTrained;
public Dog(String name, int age, double weight, String breed) {
super(name, age, weight); // 调用父类构造方法
this.breed = breed;
this.isTrained = false;
}
@Override
public void makeSound() {
System.out.println(name + " barks: Woof! Woof!");
}
@Override
public void move() {
System.out.println(name + " runs on four legs");
}
// 子类特有的方法
public void fetch(String item) {
System.out.println(name + " fetches the " + item);
}
public void train() {
isTrained = true;
System.out.println(name + " has been trained");
}
// 重写父类方法,添加特定行为
@Override
public void eat(String food) {
if (food.equals("chocolate")) {
System.out.println("Warning: Chocolate is toxic to dogs!");
return;
}
super.eat(food); // 调用父类方法
if (isTrained) {
System.out.println(name + " sits after eating (good dog!)");
}
}
public String getBreed() { return breed; }
public boolean isTrained() { return isTrained; }
}
public class Cat extends Animal {
private boolean isIndoor;
private int livesRemaining;
public Cat(String name, int age, double weight, boolean isIndoor) {
super(name, age, weight);
this.isIndoor = isIndoor;
this.livesRemaining = 9; // 猫有九条命
}
@Override
public void makeSound() {
System.out.println(name + " meows: Meow! Meow!");
}
@Override
public void move() {
System.out.println(name + " walks gracefully and can climb");
}
public void purr() {
System.out.println(name + " purrs contentedly");
}
public void hunt() {
if (!isIndoor) {
System.out.println(name + " is hunting mice");
} else {
System.out.println(name + " is hunting dust bunnies");
}
}
@Override
public void sleep(int hours) {
super.sleep(hours);
if (hours > 12) {
System.out.println(name + " is living the cat life!");
}
}
public boolean isIndoor() { return isIndoor; }
public int getLivesRemaining() { return livesRemaining; }
}
// 使用示例
public class AnimalDemo {
public static void main(String[] args) {
Dog dog = new Dog("Buddy", 3, 25.5, "Golden Retriever");
Cat cat = new Cat("Whiskers", 2, 4.2, true);
// 多态性:使用父类引用指向子类对象
Animal[] animals = {dog, cat};
for (Animal animal : animals) {
System.out.println(animal);
animal.makeSound();
animal.move();
animal.eat("food");
animal.sleep(8);
System.out.println();
}
// 使用子类特有的方法
dog.fetch("ball");
dog.train();
dog.eat("treats");
cat.purr();
cat.hunt();
cat.sleep(16);
}
}
2.3.2 继承的类型
1. 单继承 vs 多继承
# Python支持多继承
class Flyable:
def fly(self):
print("Flying in the sky")
def land(self):
print("Landing safely")
class Swimmable:
def swim(self):
print("Swimming in water")
def dive(self):
print("Diving underwater")
class Walkable:
def walk(self):
print("Walking on ground")
def run(self):
print("Running fast")
# 多继承:鸭子可以飞、游泳和走路
class Duck(Flyable, Swimmable, Walkable):
def __init__(self, name):
self.name = name
def quack(self):
print(f"{self.name} says: Quack!")
# 可以重写继承的方法
def fly(self):
print(f"{self.name} flies with webbed feet tucked")
# 企鹅只能游泳和走路
class Penguin(Swimmable, Walkable):
def __init__(self, name):
self.name = name
def slide(self):
print(f"{self.name} slides on ice")
# 重写游泳方法
def swim(self):
print(f"{self.name} swims like a torpedo")
# 使用示例
duck = Duck("Donald")
duck.quack()
duck.fly()
duck.swim()
duck.walk()
penguin = Penguin("Pingu")
penguin.swim()
penguin.walk()
penguin.slide()
# penguin.fly() # 这会报错,因为企鹅不会飞
2. 方法解析顺序(MRO)
class A:
def method(self):
print("A.method")
class B(A):
def method(self):
print("B.method")
super().method()
class C(A):
def method(self):
print("C.method")
super().method()
class D(B, C):
def method(self):
print("D.method")
super().method()
# 查看方法解析顺序
print(D.__mro__)
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
d = D()
d.method()
# 输出:
# D.method
# B.method
# C.method
# A.method
2.3.3 继承的最佳实践
1. 优先使用组合而非继承
// 不好的继承设计
class Employee {
protected String name;
protected double salary;
public void work() {
System.out.println(name + " is working");
}
}
class Manager extends Employee {
private List<Employee> subordinates;
public void manage() {
System.out.println(name + " is managing");
}
}
class Developer extends Employee {
private String programmingLanguage;
public void code() {
System.out.println(name + " is coding in " + programmingLanguage);
}
}
// 问题:如果需要一个既是Manager又是Developer的角色怎么办?
// Java不支持多继承,这种设计就有问题了
// 更好的组合设计
class Employee {
private String name;
private double salary;
private List<Role> roles;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
this.roles = new ArrayList<>();
}
public void addRole(Role role) {
roles.add(role);
}
public void performDuties() {
System.out.println(name + " is performing duties:");
for (Role role : roles) {
role.performDuty();
}
}
// Getters and setters
public String getName() { return name; }
public double getSalary() { return salary; }
}
interface Role {
void performDuty();
}
class ManagerRole implements Role {
private List<Employee> subordinates;
public ManagerRole() {
this.subordinates = new ArrayList<>();
}
@Override
public void performDuty() {
System.out.println("Managing team of " + subordinates.size() + " people");
}
public void addSubordinate(Employee employee) {
subordinates.add(employee);
}
}
class DeveloperRole implements Role {
private String programmingLanguage;
public DeveloperRole(String language) {
this.programmingLanguage = language;
}
@Override
public void performDuty() {
System.out.println("Coding in " + programmingLanguage);
}
}
class ArchitectRole implements Role {
@Override
public void performDuty() {
System.out.println("Designing system architecture");
}
}
// 使用示例
public class EmployeeDemo {
public static void main(String[] args) {
Employee john = new Employee("John", 80000);
// John既是管理者又是开发者
john.addRole(new ManagerRole());
john.addRole(new DeveloperRole("Java"));
john.addRole(new ArchitectRole());
john.performDuties();
Employee jane = new Employee("Jane", 70000);
jane.addRole(new DeveloperRole("Python"));
jane.performDuties();
}
}
2.4 多态(Polymorphism)
2.4.1 多态的概念
多态允许不同类的对象对同一消息做出不同的响应,实现”一个接口,多种实现”。
2.4.2 运行时多态(动态多态)
#include <iostream>
#include <vector>
#include <memory>
// 基类
class Shape {
protected:
std::string color;
public:
Shape(const std::string& color) : color(color) {}
// 虚函数实现多态
virtual double getArea() const = 0;
virtual double getPerimeter() const = 0;
virtual void draw() const {
std::cout << "Drawing a " << color << " shape" << std::endl;
}
// 虚析构函数
virtual ~Shape() = default;
std::string getColor() const { return color; }
};
// 派生类
class Circle : public Shape {
private:
double radius;
public:
Circle(const std::string& color, double radius)
: Shape(color), radius(radius) {}
double getArea() const override {
return 3.14159 * radius * radius;
}
double getPerimeter() const override {
return 2 * 3.14159 * radius;
}
void draw() const override {
std::cout << "Drawing a " << color << " circle with radius " << radius << std::endl;
}
double getRadius() const { return radius; }
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(const std::string& color, double width, double height)
: Shape(color), width(width), height(height) {}
double getArea() const override {
return width * height;
}
double getPerimeter() const override {
return 2 * (width + height);
}
void draw() const override {
std::cout << "Drawing a " << color << " rectangle (" << width << "x" << height << ")" << std::endl;
}
double getWidth() const { return width; }
double getHeight() const { return height; }
};
class Triangle : public Shape {
private:
double side1, side2, side3;
public:
Triangle(const std::string& color, double s1, double s2, double s3)
: Shape(color), side1(s1), side2(s2), side3(s3) {}
double getArea() const override {
// 使用海伦公式
double s = (side1 + side2 + side3) / 2;
return std::sqrt(s * (s - side1) * (s - side2) * (s - side3));
}
double getPerimeter() const override {
return side1 + side2 + side3;
}
void draw() const override {
std::cout << "Drawing a " << color << " triangle (" << side1 << ", "
<< side2 << ", " << side3 << ")" << std::endl;
}
};
// 多态函数
void printShapeInfo(const Shape& shape) {
shape.draw();
std::cout << "Area: " << shape.getArea() << std::endl;
std::cout << "Perimeter: " << shape.getPerimeter() << std::endl;
std::cout << "Color: " << shape.getColor() << std::endl;
std::cout << "---" << std::endl;
}
double calculateTotalArea(const std::vector<std::unique_ptr<Shape>>& shapes) {
double total = 0;
for (const auto& shape : shapes) {
total += shape->getArea();
}
return total;
}
int main() {
// 创建不同类型的形状
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>("red", 5.0));
shapes.push_back(std::make_unique<Rectangle>("blue", 4.0, 6.0));
shapes.push_back(std::make_unique<Triangle>("green", 3.0, 4.0, 5.0));
// 多态调用
for (const auto& shape : shapes) {
printShapeInfo(*shape);
}
// 计算总面积
double totalArea = calculateTotalArea(shapes);
std::cout << "Total area of all shapes: " << totalArea << std::endl;
return 0;
}
2.4.3 编译时多态(静态多态)
1. 函数重载
public class Calculator {
// 方法重载:相同方法名,不同参数
public int add(int a, int b) {
System.out.println("Adding two integers");
return a + b;
}
public double add(double a, double b) {
System.out.println("Adding two doubles");
return a + b;
}
public int add(int a, int b, int c) {
System.out.println("Adding three integers");
return a + b + c;
}
public String add(String a, String b) {
System.out.println("Concatenating two strings");
return a + b;
}
// 可变参数
public int add(int... numbers) {
System.out.println("Adding variable number of integers");
int sum = 0;
for (int num : numbers) {
sum += num;
}
return sum;
}
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(5, 3)); // 调用add(int, int)
System.out.println(calc.add(5.5, 3.2)); // 调用add(double, double)
System.out.println(calc.add(1, 2, 3)); // 调用add(int, int, int)
System.out.println(calc.add("Hello", "World")); // 调用add(String, String)
System.out.println(calc.add(1, 2, 3, 4, 5)); // 调用add(int...)
}
}
2. 泛型(模板)
#include <iostream>
#include <vector>
#include <string>
// 函数模板
template<typename T>
T findMax(const std::vector<T>& vec) {
if (vec.empty()) {
throw std::invalid_argument("Vector is empty");
}
T max = vec[0];
for (const T& element : vec) {
if (element > max) {
max = element;
}
}
return max;
}
// 类模板
template<typename T>
class Stack {
private:
std::vector<T> elements;
public:
void push(const T& element) {
elements.push_back(element);
}
T pop() {
if (elements.empty()) {
throw std::runtime_error("Stack is empty");
}
T top = elements.back();
elements.pop_back();
return top;
}
const T& top() const {
if (elements.empty()) {
throw std::runtime_error("Stack is empty");
}
return elements.back();
}
bool empty() const {
return elements.empty();
}
size_t size() const {
return elements.size();
}
};
// 模板特化
template<>
class Stack<bool> {
private:
std::vector<char> elements; // 使用char而不是bool来避免vector<bool>的问题
public:
void push(bool element) {
elements.push_back(element ? 1 : 0);
}
bool pop() {
if (elements.empty()) {
throw std::runtime_error("Stack is empty");
}
char top = elements.back();
elements.pop_back();
return top != 0;
}
bool top() const {
if (elements.empty()) {
throw std::runtime_error("Stack is empty");
}
return elements.back() != 0;
}
bool empty() const {
return elements.empty();
}
size_t size() const {
return elements.size();
}
};
int main() {
// 使用函数模板
std::vector<int> intVec = {1, 5, 3, 9, 2};
std::vector<std::string> stringVec = {"apple", "banana", "cherry"};
std::cout << "Max int: " << findMax(intVec) << std::endl;
std::cout << "Max string: " << findMax(stringVec) << std::endl;
// 使用类模板
Stack<int> intStack;
intStack.push(10);
intStack.push(20);
intStack.push(30);
while (!intStack.empty()) {
std::cout << "Popped: " << intStack.pop() << std::endl;
}
Stack<std::string> stringStack;
stringStack.push("first");
stringStack.push("second");
stringStack.push("third");
while (!stringStack.empty()) {
std::cout << "Popped: " << stringStack.pop() << std::endl;
}
// 使用特化的bool栈
Stack<bool> boolStack;
boolStack.push(true);
boolStack.push(false);
boolStack.push(true);
while (!boolStack.empty()) {
std::cout << "Popped: " << (boolStack.pop() ? "true" : "false") << std::endl;
}
return 0;
}
2.5 接口和抽象类
2.5.1 接口(Interface)
接口定义了类必须实现的方法契约,但不提供实现。
// 接口定义
public interface Drawable {
// 接口中的方法默认是public abstract
void draw();
void setColor(String color);
String getColor();
// Java 8+支持默认方法
default void highlight() {
System.out.println("Highlighting the drawable object");
}
// Java 8+支持静态方法
static void printInfo() {
System.out.println("This is a drawable interface");
}
// 接口中的常量默认是public static final
String DEFAULT_COLOR = "BLACK";
}
public interface Resizable {
void resize(double factor);
double getArea();
default void doubleSize() {
resize(2.0);
}
}
// 实现多个接口
public class Circle implements Drawable, Resizable {
private double radius;
private String color;
private double x, y; // 圆心坐标
public Circle(double radius, double x, double y) {
this.radius = radius;
this.x = x;
this.y = y;
this.color = Drawable.DEFAULT_COLOR;
}
// 实现Drawable接口
@Override
public void draw() {
System.out.println("Drawing a " + color + " circle at (" + x + ", " + y + ") with radius " + radius);
}
@Override
public void setColor(String color) {
this.color = color;
}
@Override
public String getColor() {
return color;
}
// 实现Resizable接口
@Override
public void resize(double factor) {
if (factor > 0) {
radius *= factor;
System.out.println("Circle resized by factor " + factor + ", new radius: " + radius);
}
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
// 圆特有的方法
public double getRadius() {
return radius;
}
public void move(double newX, double newY) {
this.x = newX;
this.y = newY;
System.out.println("Circle moved to (" + x + ", " + y + ")");
}
}
public class Rectangle implements Drawable, Resizable {
private double width, height;
private String color;
private double x, y;
public Rectangle(double width, double height, double x, double y) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.color = Drawable.DEFAULT_COLOR;
}
@Override
public void draw() {
System.out.println("Drawing a " + color + " rectangle at (" + x + ", " + y + ") with size " + width + "x" + height);
}
@Override
public void setColor(String color) {
this.color = color;
}
@Override
public String getColor() {
return color;
}
@Override
public void resize(double factor) {
if (factor > 0) {
width *= factor;
height *= factor;
System.out.println("Rectangle resized by factor " + factor + ", new size: " + width + "x" + height);
}
}
@Override
public double getArea() {
return width * height;
}
public double getWidth() { return width; }
public double getHeight() { return height; }
}
// 使用接口的示例
public class InterfaceDemo {
public static void main(String[] args) {
// 多态:使用接口引用
Drawable[] drawables = {
new Circle(5.0, 10, 20),
new Rectangle(4.0, 6.0, 30, 40)
};
// 绘制所有图形
for (Drawable drawable : drawables) {
drawable.setColor("RED");
drawable.draw();
drawable.highlight(); // 使用默认方法
}
// 调用静态方法
Drawable.printInfo();
// 调整大小
Resizable[] resizables = {
new Circle(3.0, 0, 0),
new Rectangle(2.0, 3.0, 0, 0)
};
for (Resizable resizable : resizables) {
System.out.println("Original area: " + resizable.getArea());
resizable.doubleSize(); // 使用默认方法
System.out.println("New area: " + resizable.getArea());
}
}
}
2.5.2 抽象类(Abstract Class)
抽象类可以包含抽象方法和具体方法,提供部分实现。
from abc import ABC, abstractmethod
import math
# 抽象基类
class Vehicle(ABC):
def __init__(self, brand, model, year):
self.brand = brand
self.model = model
self.year = year
self.is_running = False
self.fuel_level = 100 # 百分比
# 抽象方法,子类必须实现
@abstractmethod
def start_engine(self):
pass
@abstractmethod
def stop_engine(self):
pass
@abstractmethod
def get_max_speed(self):
pass
@abstractmethod
def get_fuel_efficiency(self):
pass
# 具体方法,子类可以直接使用或重写
def honk(self):
print(f"{self.brand} {self.model} honks: Beep! Beep!")
def check_fuel(self):
if self.fuel_level < 10:
print("Warning: Low fuel!")
return self.fuel_level
def refuel(self, amount):
self.fuel_level = min(100, self.fuel_level + amount)
print(f"Refueled. Current fuel level: {self.fuel_level}%")
def drive(self, distance):
if not self.is_running:
print("Start the engine first!")
return False
fuel_needed = distance / self.get_fuel_efficiency()
if fuel_needed > self.fuel_level:
print("Not enough fuel for this trip!")
return False
self.fuel_level -= fuel_needed
print(f"Drove {distance} km. Remaining fuel: {self.fuel_level:.1f}%")
return True
def get_info(self):
return f"{self.year} {self.brand} {self.model}"
def __str__(self):
status = "Running" if self.is_running else "Stopped"
return f"{self.get_info()} - Status: {status}, Fuel: {self.fuel_level}%"
# 具体子类
class Car(Vehicle):
def __init__(self, brand, model, year, num_doors=4):
super().__init__(brand, model, year)
self.num_doors = num_doors
self.max_speed = 180 # km/h
self.fuel_efficiency = 15 # km per liter
def start_engine(self):
if not self.is_running:
self.is_running = True
print(f"{self.get_info()} engine started with a gentle purr")
else:
print("Engine is already running")
def stop_engine(self):
if self.is_running:
self.is_running = False
print(f"{self.get_info()} engine stopped")
else:
print("Engine is already stopped")
def get_max_speed(self):
return self.max_speed
def get_fuel_efficiency(self):
return self.fuel_efficiency
def open_trunk(self):
print(f"{self.get_info()} trunk opened")
def lock_doors(self):
print(f"All {self.num_doors} doors locked")
class Motorcycle(Vehicle):
def __init__(self, brand, model, year, engine_size):
super().__init__(brand, model, year)
self.engine_size = engine_size # cc
self.max_speed = 200
self.fuel_efficiency = 25
def start_engine(self):
if not self.is_running:
self.is_running = True
print(f"{self.get_info()} engine started with a loud roar!")
else:
print("Engine is already running")
def stop_engine(self):
if self.is_running:
self.is_running = False
print(f"{self.get_info()} engine stopped")
else:
print("Engine is already stopped")
def get_max_speed(self):
return self.max_speed
def get_fuel_efficiency(self):
return self.fuel_efficiency
def wheelie(self):
if self.is_running:
print(f"{self.get_info()} performs a wheelie!")
else:
print("Start the engine first to perform a wheelie!")
# 重写父类方法
def honk(self):
print(f"{self.brand} {self.model} revs: Vroom! Vroom!")
class Truck(Vehicle):
def __init__(self, brand, model, year, cargo_capacity):
super().__init__(brand, model, year)
self.cargo_capacity = cargo_capacity # tons
self.current_load = 0
self.max_speed = 120
self.fuel_efficiency = 8
def start_engine(self):
if not self.is_running:
self.is_running = True
print(f"{self.get_info()} diesel engine started with a rumble")
else:
print("Engine is already running")
def stop_engine(self):
if self.is_running:
self.is_running = False
print(f"{self.get_info()} engine stopped")
else:
print("Engine is already stopped")
def get_max_speed(self):
# 载重影响最大速度
load_factor = self.current_load / self.cargo_capacity
return self.max_speed * (1 - load_factor * 0.3)
def get_fuel_efficiency(self):
# 载重影响油耗
load_factor = self.current_load / self.cargo_capacity
return self.fuel_efficiency * (1 - load_factor * 0.4)
def load_cargo(self, weight):
if self.current_load + weight <= self.cargo_capacity:
self.current_load += weight
print(f"Loaded {weight} tons. Current load: {self.current_load}/{self.cargo_capacity} tons")
else:
print(f"Cannot load {weight} tons. Exceeds capacity!")
def unload_cargo(self, weight):
if weight <= self.current_load:
self.current_load -= weight
print(f"Unloaded {weight} tons. Current load: {self.current_load}/{self.cargo_capacity} tons")
else:
print(f"Cannot unload {weight} tons. Not enough cargo!")
# 使用示例
def main():
# 创建不同类型的车辆
vehicles = [
Car("Toyota", "Camry", 2023),
Motorcycle("Harley-Davidson", "Street 750", 2022, 750),
Truck("Volvo", "FH16", 2021, 40)
]
print("=== Vehicle Information ===")
for vehicle in vehicles:
print(vehicle)
print(f"Max Speed: {vehicle.get_max_speed()} km/h")
print(f"Fuel Efficiency: {vehicle.get_fuel_efficiency()} km/L")
print()
print("=== Starting Engines ===")
for vehicle in vehicles:
vehicle.start_engine()
vehicle.honk()
print("\n=== Driving Test ===")
car = vehicles[0]
motorcycle = vehicles[1]
truck = vehicles[2]
# 汽车测试
car.drive(100)
car.lock_doors()
car.open_trunk()
# 摩托车测试
motorcycle.drive(150)
motorcycle.wheelie()
# 卡车测试
truck.load_cargo(20)
truck.drive(200)
print(f"Truck max speed with load: {truck.get_max_speed():.1f} km/h")
print(f"Truck fuel efficiency with load: {truck.get_fuel_efficiency():.1f} km/L")
print("\n=== Final Status ===")
for vehicle in vehicles:
print(vehicle)
vehicle.check_fuel()
vehicle.stop_engine()
if __name__ == "__main__":
main()
2.5.3 接口 vs 抽象类
特性 | 接口 | 抽象类 |
---|---|---|
多重继承 | 支持 | 不支持(大多数语言) |
方法实现 | 只能有默认方法(Java 8+) | 可以有具体方法 |
属性 | 只能有常量 | 可以有实例变量 |
构造方法 | 不能有 | 可以有 |
访问修饰符 | 方法默认public | 可以有各种访问级别 |
设计目的 | 定义契约 | 提供通用实现 |
2.6 对象间关系
2.6.1 关联(Association)
关联表示两个类之间的一般性连接。
// 关联关系示例
public class Student {
private String name;
private String studentId;
private List<Course> enrolledCourses;
public Student(String name, String studentId) {
this.name = name;
this.studentId = studentId;
this.enrolledCourses = new ArrayList<>();
}
public void enrollInCourse(Course course) {
if (!enrolledCourses.contains(course)) {
enrolledCourses.add(course);
course.addStudent(this); // 双向关联
}
}
public void dropCourse(Course course) {
if (enrolledCourses.contains(course)) {
enrolledCourses.remove(course);
course.removeStudent(this);
}
}
// Getters
public String getName() { return name; }
public String getStudentId() { return studentId; }
public List<Course> getEnrolledCourses() { return new ArrayList<>(enrolledCourses); }
}
public class Course {
private String courseName;
private String courseCode;
private List<Student> enrolledStudents;
private int maxCapacity;
public Course(String courseName, String courseCode, int maxCapacity) {
this.courseName = courseName;
this.courseCode = courseCode;
this.maxCapacity = maxCapacity;
this.enrolledStudents = new ArrayList<>();
}
public boolean addStudent(Student student) {
if (enrolledStudents.size() < maxCapacity && !enrolledStudents.contains(student)) {
enrolledStudents.add(student);
return true;
}
return false;
}
public void removeStudent(Student student) {
enrolledStudents.remove(student);
}
// Getters
public String getCourseName() { return courseName; }
public String getCourseCode() { return courseCode; }
public List<Student> getEnrolledStudents() { return new ArrayList<>(enrolledStudents); }
public int getCurrentEnrollment() { return enrolledStudents.size(); }
public int getMaxCapacity() { return maxCapacity; }
}
2.6.2 聚合(Aggregation)
聚合是一种特殊的关联,表示”has-a”关系,部分可以独立于整体存在。
// 聚合关系示例
public class Department {
private String name;
private List<Employee> employees;
private Employee manager;
public Department(String name) {
this.name = name;
this.employees = new ArrayList<>();
}
public void addEmployee(Employee employee) {
if (!employees.contains(employee)) {
employees.add(employee);
employee.setDepartment(this);
}
}
public void removeEmployee(Employee employee) {
if (employees.contains(employee)) {
employees.remove(employee);
employee.setDepartment(null); // 员工可以独立存在
}
}
public void setManager(Employee manager) {
if (employees.contains(manager)) {
this.manager = manager;
}
}
// Getters
public String getName() { return name; }
public List<Employee> getEmployees() { return new ArrayList<>(employees); }
public Employee getManager() { return manager; }
}
public class Employee {
private String name;
private String employeeId;
private Department department; // 员工属于某个部门,但可以独立存在
public Employee(String name, String employeeId) {
this.name = name;
this.employeeId = employeeId;
}
public void setDepartment(Department department) {
this.department = department;
}
// Getters
public String getName() { return name; }
public String getEmployeeId() { return employeeId; }
public Department getDepartment() { return department; }
}
2.6.3 组合(Composition)
组合是一种强聚合,表示”part-of”关系,部分不能独立于整体存在。
// 组合关系示例
public class House {
private String address;
private List<Room> rooms;
private Roof roof;
private Foundation foundation;
public House(String address) {
this.address = address;
this.rooms = new ArrayList<>();
// 房子创建时,屋顶和地基也被创建(强依赖)
this.roof = new Roof("Tile Roof");
this.foundation = new Foundation("Concrete Foundation");
}
public void addRoom(String roomType, double area) {
Room room = new Room(roomType, area); // 房间属于房子,不能独立存在
rooms.add(room);
}
public void removeRoom(Room room) {
rooms.remove(room);
// 房间被移除后就不存在了(组合关系)
}
public double getTotalArea() {
return rooms.stream().mapToDouble(Room::getArea).sum();
}
// Getters
public String getAddress() { return address; }
public List<Room> getRooms() { return new ArrayList<>(rooms); }
public Roof getRoof() { return roof; }
public Foundation getFoundation() { return foundation; }
@Override
public String toString() {
return "House at " + address + " with " + rooms.size() + " rooms";
}
}
// 房间类 - 强依赖于房子
class Room {
private String type;
private double area;
public Room(String type, double area) {
this.type = type;
this.area = area;
}
public String getType() { return type; }
public double getArea() { return area; }
@Override
public String toString() {
return type + " (" + area + " sq.m)";
}
}
class Roof {
private String material;
public Roof(String material) {
this.material = material;
}
public String getMaterial() { return material; }
}
class Foundation {
private String type;
public Foundation(String type) {
this.type = type;
}
public String getType() { return type; }
}
// 使用示例
public class CompositionDemo {
public static void main(String[] args) {
House house = new House("123 Main Street");
house.addRoom("Living Room", 25.0);
house.addRoom("Kitchen", 15.0);
house.addRoom("Bedroom", 20.0);
house.addRoom("Bathroom", 8.0);
System.out.println(house);
System.out.println("Total area: " + house.getTotalArea() + " sq.m");
System.out.println("Roof: " + house.getRoof().getMaterial());
System.out.println("Foundation: " + house.getFoundation().getType());
// 当房子被销毁时,所有房间、屋顶、地基也会被销毁
}
}
2.6.4 依赖(Dependency)
依赖是最弱的关系,表示一个类使用另一个类。
// 依赖关系示例
public class EmailService {
public void sendEmail(String to, String subject, String body) {
System.out.println("Sending email to: " + to);
System.out.println("Subject: " + subject);
System.out.println("Body: " + body);
}
}
public class SMSService {
public void sendSMS(String phoneNumber, String message) {
System.out.println("Sending SMS to: " + phoneNumber);
System.out.println("Message: " + message);
}
}
public class NotificationManager {
// 依赖关系:NotificationManager使用EmailService和SMSService
// 但不持有它们的引用
public void sendNotification(String type, String recipient, String message) {
switch (type.toLowerCase()) {
case "email":
EmailService emailService = new EmailService(); // 临时依赖
emailService.sendEmail(recipient, "Notification", message);
break;
case "sms":
SMSService smsService = new SMSService(); // 临时依赖
smsService.sendSMS(recipient, message);
break;
default:
System.out.println("Unknown notification type: " + type);
}
}
// 通过参数依赖
public void sendEmailNotification(EmailService emailService, String to, String message) {
emailService.sendEmail(to, "Alert", message);
}
}
2.6.5 关系总结
# 对象关系总结示例
class University:
"""大学类 - 展示各种对象关系"""
def __init__(self, name):
self.name = name
self.departments = [] # 聚合:大学有多个系
self.campus = Campus(name + " Campus") # 组合:校园属于大学
self.library = Library(name + " Library") # 组合:图书馆属于大学
def add_department(self, department):
"""聚合关系:系可以独立存在"""
self.departments.append(department)
department.university = self
def remove_department(self, department):
"""移除系,但系可以独立存在"""
if department in self.departments:
self.departments.remove(department)
department.university = None
def organize_event(self, event_manager):
"""依赖关系:临时使用事件管理器"""
event_manager.organize("University Open Day", self.campus)
class Department:
"""系类"""
def __init__(self, name):
self.name = name
self.university = None # 聚合:属于大学但可独立存在
self.professors = [] # 关联:教授与系的关系
self.courses = [] # 聚合:课程属于系
def hire_professor(self, professor):
"""关联关系:教授与系关联"""
self.professors.append(professor)
professor.departments.append(self)
def add_course(self, course):
"""聚合关系:课程属于系"""
self.courses.append(course)
course.department = self
class Professor:
"""教授类"""
def __init__(self, name, specialization):
self.name = name
self.specialization = specialization
self.departments = [] # 关联:可以在多个系任教
self.office = Office(f"{name}'s Office") # 组合:办公室属于教授
def teach_course(self, course, students):
"""依赖关系:临时使用课程和学生"""
print(f"{self.name} is teaching {course.name} to {len(students)} students")
class Student:
"""学生类"""
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
self.enrolled_courses = [] # 关联:学生选课
self.transcript = Transcript(student_id) # 组合:成绩单属于学生
def enroll_in_course(self, course):
"""关联关系:学生与课程关联"""
self.enrolled_courses.append(course)
course.students.append(self)
class Course:
"""课程类"""
def __init__(self, name, code, credits):
self.name = name
self.code = code
self.credits = credits
self.department = None # 聚合:属于某个系
self.students = [] # 关联:与学生关联
self.assignments = [] # 组合:作业属于课程
def add_assignment(self, title, due_date):
"""组合关系:作业属于课程"""
assignment = Assignment(title, due_date)
self.assignments.append(assignment)
return assignment
class Campus:
"""校园类 - 组合关系"""
def __init__(self, name):
self.name = name
self.buildings = [] # 组合:建筑属于校园
def add_building(self, building_name, building_type):
building = Building(building_name, building_type)
self.buildings.append(building)
return building
class Library:
"""图书馆类 - 组合关系"""
def __init__(self, name):
self.name = name
self.books = [] # 组合:图书属于图书馆
def add_book(self, title, author):
book = Book(title, author)
self.books.append(book)
return book
class Office:
"""办公室类 - 组合关系"""
def __init__(self, room_number):
self.room_number = room_number
self.equipment = [] # 组合:设备属于办公室
class Transcript:
"""成绩单类 - 组合关系"""
def __init__(self, student_id):
self.student_id = student_id
self.grades = [] # 组合:成绩属于成绩单
class Assignment:
"""作业类 - 组合关系"""
def __init__(self, title, due_date):
self.title = title
self.due_date = due_date
class Building:
"""建筑类 - 组合关系"""
def __init__(self, name, building_type):
self.name = name
self.type = building_type
class Book:
"""图书类 - 组合关系"""
def __init__(self, title, author):
self.title = title
self.author = author
class EventManager:
"""事件管理器 - 依赖关系"""
def organize(self, event_name, venue):
print(f"Organizing {event_name} at {venue.name}")
# 使用示例
def main():
# 创建大学
university = University("Tech University")
# 创建系(聚合关系)
cs_dept = Department("Computer Science")
math_dept = Department("Mathematics")
university.add_department(cs_dept)
university.add_department(math_dept)
# 创建教授(关联关系)
prof_smith = Professor("Dr. Smith", "Algorithms")
prof_jones = Professor("Dr. Jones", "Calculus")
cs_dept.hire_professor(prof_smith)
math_dept.hire_professor(prof_jones)
# 创建课程(聚合关系)
algo_course = Course("Data Structures and Algorithms", "CS301", 3)
calc_course = Course("Calculus I", "MATH101", 4)
cs_dept.add_course(algo_course)
math_dept.add_course(calc_course)
# 创建学生(关联关系)
student1 = Student("Alice", "S001")
student2 = Student("Bob", "S002")
student1.enroll_in_course(algo_course)
student1.enroll_in_course(calc_course)
student2.enroll_in_course(algo_course)
# 添加作业(组合关系)
algo_course.add_assignment("Binary Tree Implementation", "2024-02-15")
calc_course.add_assignment("Derivative Problems", "2024-02-10")
# 使用事件管理器(依赖关系)
event_manager = EventManager()
university.organize_event(event_manager)
# 教授授课(依赖关系)
prof_smith.teach_course(algo_course, algo_course.students)
print(f"\n{university.name} has {len(university.departments)} departments")
print(f"CS Department has {len(cs_dept.courses)} courses and {len(cs_dept.professors)} professors")
print(f"Algorithm course has {len(algo_course.students)} students enrolled")
if __name__ == "__main__":
main()
2.7 本章总结
2.7.1 核心概念回顾
- 类与对象:类是模板,对象是实例
- 封装:隐藏内部实现,提供受控访问
- 继承:代码复用和层次化设计
- 多态:一个接口,多种实现
- 接口与抽象类:定义契约和提供部分实现
- 对象关系:关联、聚合、组合、依赖
2.7.2 设计原则
- 高内聚,低耦合
- 优先使用组合而非继承
- 面向接口编程
- 封装变化点
- 遵循SOLID原则
2.7.3 最佳实践
- 合理使用访问修饰符
- 提供清晰的接口
- 避免过深的继承层次
- 正确选择对象关系
- 编写可测试的代码
2.8 练习题
2.8.1 基础练习
设计一个图书管理系统,包含图书、读者、借阅记录等类,体现封装、继承、多态的特性。
实现一个简单的绘图系统,包含不同类型的图形(圆形、矩形、三角形),使用接口定义绘图行为。
设计一个员工管理系统,区分正式员工、临时员工、管理员等不同类型,使用抽象类和继承。
2.8.2 进阶练习
设计一个电商系统的核心类结构,包含用户、商品、订单、支付等,正确使用各种对象关系。
实现一个媒体播放器,支持不同格式的音频和视频文件,使用多态和策略模式。
设计一个游戏角色系统,包含不同职业、技能、装备等,体现组合优于继承的原则。
2.8.3 思考题
什么时候应该使用继承?什么时候应该使用组合?
如何在保持封装性的同时提供灵活的扩展性?
接口和抽象类在实际项目中如何选择使用?
下一章预告:第03章将深入学习创建型设计模式,包括单例模式、工厂模式、建造者模式等,学习如何优雅地创建对象。