====== 第六章 继承与多态 ======
===== 6.1 继承基础 =====
=== 什么是继承 ===
继承是面向对象编程的核心特性之一,允许一个类(子类/派生类)继承另一个类(父类/基类)的成员。
// 基类
public class Animal
{
public string Name { get; set; }
public int Age { get; set; }
public void Eat()
{
Console.WriteLine($"{Name} 正在吃东西");
}
public void Sleep()
{
Console.WriteLine($"{Name} 正在睡觉");
}
public virtual void MakeSound()
{
Console.WriteLine("动物发出声音");
}
}
// 派生类
public class Dog : Animal
{
public string Breed { get; set; }
public void Fetch()
{
Console.WriteLine($"{Name} 正在捡球");
}
// 重写基类方法
public override void MakeSound()
{
Console.WriteLine($"{Name} 说: 汪汪!");
}
}
// 使用
Dog dog = new Dog { Name = "小黑", Age = 3, Breed = "金毛" };
dog.Eat(); // 继承自Animal
dog.Fetch(); // Dog自己的方法
dog.MakeSound(); // 调用重写的方法
=== 构造函数继承 ===
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
public class Employee : Person
{
public string EmployeeId { get; set; }
public decimal Salary { get; set; }
// 调用基类构造函数
public Employee(string name, int age, string employeeId, decimal salary)
: base(name, age)
{
EmployeeId = employeeId;
Salary = salary;
}
}
// 使用
Employee emp = new Employee("张三", 30, "E001", 5000);
===== 6.2 方法重写(Override) =====
=== virtual和override ===
public class Shape
{
public string Name { get; set; }
// 虚方法:允许子类重写
public virtual double CalculateArea()
{
return 0;
}
public virtual void Draw()
{
Console.WriteLine($"绘制{Name}");
}
}
public class Circle : Shape
{
public double Radius { get; set; }
public Circle(double radius)
{
Name = "圆形";
Radius = radius;
}
// 重写基类方法
public override double CalculateArea()
{
return Math.PI * Radius * Radius;
}
public override void Draw()
{
base.Draw(); // 调用基类实现
Console.WriteLine($"半径: {Radius}");
}
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Name = "矩形";
Width = width;
Height = height;
}
public override double CalculateArea()
{
return Width * Height;
}
}
=== sealed关键字 ===
public class BaseClass
{
public virtual void Method() { }
}
public class DerivedClass : BaseClass
{
// 阻止进一步重写
public sealed override void Method() { }
}
// 无法重写sealed方法
// public class FurtherDerived : DerivedClass
// {
// public override void Method() { } // 编译错误
// }
===== 6.3 抽象类 =====
=== 抽象类和抽象方法 ===
// 抽象类:不能被实例化
public abstract class Vehicle
{
public string Brand { get; set; }
public string Model { get; set; }
// 普通方法
public void Start()
{
Console.WriteLine($"{Brand} {Model} 启动");
}
// 抽象方法:必须在子类中实现
public abstract void Drive();
// 抽象属性
public abstract int MaxSpeed { get; }
}
public class Car : Vehicle
{
public int TrunkCapacity { get; set; }
// 实现抽象方法
public override void Drive()
{
Console.WriteLine("汽车在公路上行驶");
}
public override int MaxSpeed => 200;
}
public class Motorcycle : Vehicle
{
public bool HasSidecar { get; set; }
public override void Drive()
{
Console.WriteLine("摩托车灵活穿梭");
}
public override int MaxSpeed => 150;
}
// 使用
Vehicle myCar = new Car { Brand = "Toyota", Model = "Corolla" };
Vehicle myBike = new Motorcycle { Brand = "Honda", Model = "CBR" };
myCar.Drive(); // 输出: 汽车在公路上行驶
myBike.Drive(); // 输出: 摩托车灵活穿梭
===== 6.4 接口 =====
=== 接口定义 ===
接口定义一组行为规范,类可以实现多个接口。
// 定义接口
public interface IFlyable
{
void Fly();
int MaxAltitude { get; }
}
public interface ISwimmable
{
void Swim();
int MaxDepth { get; }
}
public interface IHuntable
{
void Hunt();
}
=== 实现接口 ===
// 实现多个接口
public class Duck : Animal, IFlyable, ISwimmable
{
public int MaxAltitude => 1000;
public int MaxDepth => 5;
public void Fly()
{
Console.WriteLine($"{Name} 在飞翔");
}
public void Swim()
{
Console.WriteLine($"{Name} 在游泳");
}
public override void MakeSound()
{
Console.WriteLine($"{Name} 说: 嘎嘎!");
}
}
// 使用
Duck duck = new Duck { Name = "唐老鸭" };
duck.Fly();
duck.Swim();
duck.MakeSound();
=== 显式接口实现 ===
public interface IEnglish
{
void Speak();
}
public interface IChinese
{
void Speak();
}
public class BilingualPerson : IEnglish, IChinese
{
// 显式实现接口
void IEnglish.Speak()
{
Console.WriteLine("Hello!");
}
void IChinese.Speak()
{
Console.WriteLine("你好!");
}
// 默认实现
public void Speak()
{
Console.WriteLine("Speaking...");
}
}
// 使用
var person = new BilingualPerson();
person.Speak(); // 调用默认实现
IEnglish english = person;
english.Speak(); // 调用英语实现
IChinese chinese = person;
chinese.Speak(); // 调用中文实现
===== 6.5 多态 =====
=== 编译时多态(重载) ===
public class Calculator
{
// 方法重载
public int Add(int a, int b) => a + b;
public double Add(double a, double b) => a + b;
public int Add(int a, int b, int c) => a + b + c;
public string Add(string a, string b) => a + b;
}
=== 运行时多态(重写) ===
public class PolymorphismDemo
{
public static void Main()
{
// 使用基类引用指向派生类对象
Shape shape1 = new Circle(5);
Shape shape2 = new Rectangle(4, 6);
// 运行时确定调用哪个方法
Console.WriteLine($"形状1面积: {shape1.CalculateArea():F2}");
Console.WriteLine($"形状2面积: {shape2.CalculateArea():F2}");
// 数组多态
Shape[] shapes = new Shape[]
{
new Circle(3),
new Rectangle(4, 5),
new Circle(2)
};
double totalArea = 0;
foreach (Shape shape in shapes)
{
totalArea += shape.CalculateArea();
shape.Draw();
Console.WriteLine();
}
Console.WriteLine($"总面积: {totalArea:F2}");
}
}
===== 6.6 类型转换和判断 =====
=== is运算符 ===
Animal animal = new Dog { Name = "小黑" };
// 类型检查
if (animal is Dog)
{
Dog dog = (Dog)animal;
dog.Fetch();
}
// 模式匹配(C# 7+)
if (animal is Dog d)
{
d.Fetch();
}
// null检查
if (animal is not null)
{
Console.WriteLine("animal不为null");
}
=== as运算符 ===
Animal animal = new Dog { Name = "小黑" };
// 安全类型转换
Dog dog = animal as Dog;
if (dog != null)
{
dog.Fetch();
}
// 转换失败返回null
Cat cat = animal as Cat; // cat为null
=== 强制类型转换 ===
Animal animal = new Dog { Name = "小黑" };
// 强制转换
Dog dog = (Dog)animal; // 成功
// 转换失败抛出异常
// Cat cat = (Cat)animal; // InvalidCastException
===== 6.7 抽象类 vs 接口 =====
| 特性 | 抽象类 | 接口 |
|------|--------|------|
| 实例化 | 不能 | 不能 |
| 实现 | 单继承 | 多实现 |
| 成员 | 可以有实现 | C# 8+可以有默认实现 |
| 字段 | 可以有 | 不能有实例字段 |
| 构造函数 | 可以有 | 不能有 |
| 访问修饰符 | 可以指定 | 默认public |
| 使用场景 | "is-a"关系 | "can-do"关系 |
// 抽象类示例 - "is-a"关系
public abstract class Bird : Animal
{
public void LayEgg()
{
Console.WriteLine("下蛋");
}
}
// 接口示例 - "can-do"关系
public interface ILogger
{
void Log(string message);
}
public class FileLogger : ILogger
{
public void Log(string message)
{
File.AppendAllText("log.txt", message + Environment.NewLine);
}
}
===== 6.8 实战:图形系统 =====
// 可绘制接口
public interface IDrawable
{
void Draw();
ConsoleColor Color { get; set; }
}
// 抽象基类
public abstract class Shape : IDrawable
{
public string Name { get; set; }
public ConsoleColor Color { get; set; } = ConsoleColor.White;
// 抽象方法
public abstract double CalculateArea();
public abstract double CalculatePerimeter();
// 虚方法
public virtual void Draw()
{
Console.ForegroundColor = Color;
Console.WriteLine($"绘制{Name}");
Console.WriteLine($" 面积: {CalculateArea():F2}");
Console.WriteLine($" 周长: {CalculatePerimeter():F2}");
Console.ResetColor();
}
// 具体方法
public void PrintInfo()
{
Console.WriteLine($"形状: {Name}");
Console.WriteLine($"颜色: {Color}");
}
}
// 圆形
public class Circle : Shape
{
public double Radius { get; set; }
public Circle(double radius)
{
Name = "圆形";
Radius = radius;
}
public override double CalculateArea() => Math.PI * Radius * Radius;
public override double CalculatePerimeter() => 2 * Math.PI * Radius;
public override void Draw()
{
base.Draw();
Console.WriteLine($" 半径: {Radius}");
}
}
// 矩形
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Name = "矩形";
Width = width;
Height = height;
}
public override double CalculateArea() => Width * Height;
public override double CalculatePerimeter() => 2 * (Width + Height);
public bool IsSquare => Width == Height;
public override void Draw()
{
base.Draw();
Console.WriteLine($" 宽: {Width}, 高: {Height}");
if (IsSquare)
{
Console.WriteLine(" 这是一个正方形!");
}
}
}
// 三角形
public class Triangle : Shape
{
public double SideA { get; set; }
public double SideB { get; set; }
public double SideC { get; set; }
public Triangle(double a, double b, double c)
{
Name = "三角形";
SideA = a;
SideB = b;
SideC = c;
}
public override double CalculateArea()
{
// 海伦公式
double s = CalculatePerimeter() / 2;
return Math.Sqrt(s * (s - SideA) * (s - SideB) * (s - SideC));
}
public override double CalculatePerimeter() => SideA + SideB + SideC;
}
// 图形管理器
public class ShapeManager
{
private List shapes = new List();
public void AddShape(Shape shape)
{
shapes.Add(shape);
}
public void DrawAll()
{
Console.WriteLine("===== 绘制所有图形 =====");
foreach (var shape in shapes)
{
shape.Draw();
Console.WriteLine();
}
}
public double GetTotalArea()
{
return shapes.Sum(s => s.CalculateArea());
}
public Shape FindLargest()
{
return shapes.OrderByDescending(s => s.CalculateArea()).FirstOrDefault();
}
public IEnumerable GetShapesOfType() where T : Shape
{
return shapes.OfType();
}
}
// 使用示例
public class ShapeDemo
{
public static void Main()
{
var manager = new ShapeManager();
manager.AddShape(new Circle(5) { Color = ConsoleColor.Red });
manager.AddShape(new Rectangle(4, 6) { Color = ConsoleColor.Green });
manager.AddShape(new Rectangle(5, 5) { Color = ConsoleColor.Blue });
manager.AddShape(new Triangle(3, 4, 5) { Color = ConsoleColor.Yellow });
manager.DrawAll();
Console.WriteLine($"总面积: {manager.GetTotalArea():F2}");
var largest = manager.FindLargest();
Console.WriteLine($"最大图形: {largest.Name}");
Console.WriteLine("\n所有矩形:");
foreach (var rect in manager.GetShapesOfType())
{
Console.WriteLine($" - {rect.Width}x{rect.Height}");
}
}
}
===== 练习题 =====
=== 基础练习 ===
1. **动物类层次**:创建动物类层次结构:
- 基类Animal(Name, Eat(), Sleep())
- 派生类Mammal(有毛发)、Bird(有羽毛)、Fish(有鳞片)
- 每个派生类重写MakeSound()
- 创建至少两个具体动物类(如Dog、Eagle、Shark)
2. **员工管理系统扩展**:在第五章员工类基础上:
- 创建Employee抽象基类
- 实现SalariedEmployee、HourlyEmployee、CommissionEmployee
- 每个类实现抽象的CalculatePay()方法
- 创建Employee数组,多态调用CalculatePay()
3. **接口实现**:实现以下接口和类:
- IPayable接口(有CalculatePayment()方法)
- Invoice类实现IPayable
- Employee类也实现IPayable
- 创建IPayable数组,统一处理不同类型的应付款项
=== 进阶练习 ===
4. **游戏角色系统**:设计RPG游戏角色系统:
- 抽象基类Character(Name, Health, Attack(), Defend())
- 派生类:Warrior、Mage、Archer
- 接口:ICanCastSpell、ICanStealth
- 实现不同角色的特殊能力
- 创建战斗系统,角色可以互相攻击
5. **插件系统**:实现一个简单的插件架构:
- IPlugin接口(Name, Version, Initialize(), Execute())
- 多个具体插件实现
- 插件管理器动态加载和执行插件
- 支持插件配置
6. **绘图应用**:扩展本章的图形系统:
- 添加更多形状(椭圆、多边形)
- 实现图层概念(Layer类包含多个Shape)
- 实现序列化和反序列化
- 添加撤销/重做功能
=== 挑战练习 ===
7. **动物园管理系统**:设计完整的动物园管理程序:
- Animal抽象基类
- 多种具体动物类
- 饲养员类(可以喂养特定类型的动物)
- 笼子/栖息地类
- 实现动物的饮食、健康、繁殖系统
8. **排序策略模式**:实现多种排序算法:
- ISortStrategy接口
- BubbleSort、QuickSort、MergeSort等实现
- 允许运行时切换排序策略
- 性能比较
===== 本章小结 =====
本章学习了C#的继承与多态:
- 继承的语法和构造函数链
- virtual和override实现方法重写
- 抽象类和抽象方法
- 接口的定义和实现
- 编译时多态(重载)和运行时多态(重写)
- 类型转换和判断
- 抽象类与接口的区别
这些是面向对象编程的核心概念,理解它们对设计良好的软件架构至关重要。