1.1.1. 继承
继承允许一个类(子类)从另一个类(基类)继承属性和方法。子类可以扩展或修改基类的行为。继承体现了“是一个”(is-a)关系,比如狗是动物的一种。继承层次过深会导致代码复杂度增加,不易维护,过度使用继承可能会导致“脆弱的基类问题”。
特点 | 说明 |
代码复用 | 子类继承基类的属性和方法,减少代码重复 |
扩展性 | 子类可以添加新的方法和属性,也可以重写基类的方法 |
多态性 | 通过基类引用可以指向子类对象,执行子类的实现 |
// 基类
public class Animal
{
? ?public void Eat()
? {
? ? ? ?Console.WriteLine("Eating...");
? }
}
// 子类
public class Dog : Animal
{
? ?public void Bark()
? {
? ? ? ?Console.WriteLine("Barking...");
? }
}
?
public class Program
{
? ?public static void Main()
? {
? ? ? ?Dog dog = new Dog();
? ? ? ?dog.Eat(); ?// 基类的方法
? ? ? ?dog.Bark(); // 子类的方法
? }
}
1.1.2. 组合(Composition)
组合是将一个类的实例作为成员变量包含在另一个类中。组合体现了“有一个”(has-a)关系,比如汽车有一个引擎。组合关系在设计时需要考虑好组件之间的依赖关系,避免过度依赖,过多的组合可能会导致类的接口过于复杂。
特点 | 说明 |
灵活性 | 类的行为可以通过组合不同的组件来实现,且组件可以独立变化 |
代码复用 | 通过组合可以实现代码复用,而不需要使用继承 |
降低耦合 | 组件之间的依赖性较低,类的变化不会影响到其他类 |
// 组成部分类
public class Engine
{
? ?public void Start()
? {
? ? ? ?Console.WriteLine("Engine starting...");
? }
}
?
// 使用组合的类
public class Car
{
? ?private Engine engine = new Engine();
?
? ?public void Start()
? {
? ? ? ?engine.Start();
? ? ? ?Console.WriteLine("Car starting...");
? }
}
?
public class Program
{
? ?public static void Main()
? {
? ? ? ?Car car = new Car();
? ? ? ?car.Start(); ?// 调用组合对象的方法
? }
}
1.1.3. 继承与组合的选择
继承适用于需要在子类中扩展或修改基类行为的情况,强调“是一个”的关系。
组合适用于通过不同组件组合实现类的行为,强调“有一个”的关系。
在实际开发中,更推荐优先使用组合,只有在明确表示子类和基类之间是“is-a”关系时才使用继承。这种方式可以让代码更加灵活、易于维护和扩展。