csharp:第六章继承与多态
目录
第六章 继承与多态
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<Shape> shapes = new List<Shape>(); 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<T> GetShapesOfType<T>() where T : Shape { return shapes.OfType<T>(); } } // 使用示例 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<Rectangle>()) { 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实现方法重写
- 抽象类和抽象方法
- 接口的定义和实现
- 编译时多态(重载)和运行时多态(重写)
- 类型转换和判断
- 抽象类与接口的区别
这些是面向对象编程的核心概念,理解它们对设计良好的软件架构至关重要。
csharp/第六章继承与多态.txt · 最后更改: 由 127.0.0.1
