C# 面向对象 - 继承与多态

11.1 继承基础

基本语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 基类
public class Animal
{
public string Name { get; set; }

public void Eat()
{
Console.WriteLine($"{Name} 正在吃东西");
}
}

// 派生类
public class Dog : Animal
{
public void Bark()
{
Console.WriteLine($"{Name} 汪汪叫");
}
}

// 使用
Dog dog = new Dog { Name = "旺财" };
dog.Eat(); // 继承的方法
dog.Bark(); // 自己的方法

11.2 base 关键字

调用基类构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 Student : Person
{
public string StudentId { get; set; }

public Student(string name, int age, string studentId)
: base(name, age) // 调用基类构造函数
{
StudentId = studentId;
}
}

调用基类方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("动物发出声音");
}
}

public class Cat : Animal
{
public override void MakeSound()
{
base.MakeSound(); // 调用基类方法
Console.WriteLine("喵喵叫");
}
}

11.3 虚方法与重写

virtual 与 override

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Shape
{
public virtual double Area()
{
return 0;
}
}

public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }

public override double Area()
{
return Width * Height;
}
}

public class Circle : Shape
{
public double Radius { get; set; }

public override double Area()
{
return Math.PI * Radius * Radius;
}
}

多态示例

1
2
3
4
5
6
7
8
9
10
11
12
13
List<Shape> shapes = new()
{
new Rectangle { Width = 5, Height = 3 },
new Circle { Radius = 4 }
};

foreach (Shape shape in shapes)
{
Console.WriteLine($"面积: {shape.Area():F2}");
}
// 输出:
// 面积: 15.00
// 面积: 50.27

11.4 隐藏基类方法

new 关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Base
{
public void Show()
{
Console.WriteLine("Base.Show");
}
}

public class Derived : Base
{
public new void Show() // 隐藏基类方法
{
Console.WriteLine("Derived.Show");
}
}

Base b = new Derived();
b.Show(); // "Base.Show"(编译时类型决定)

Derived d = new Derived();
d.Show(); // "Derived.Show"

11.5 sealed 类与方法

密封类

1
2
3
4
5
6
7
8
// 不能被继承
public sealed class Singleton
{
public static readonly Singleton Instance = new();
private Singleton() { }
}

// public class Child : Singleton { } // 错误

密封方法

1
2
3
4
5
6
7
8
9
10
11
12
public class Base
{
public virtual void Process() { }
}

public class Derived : Base
{
public sealed override void Process()
{
// 派生类不能再重写此方法
}
}

11.6 多态

运行时多态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Employee
{
public virtual decimal GetSalary() => 5000;
}

public class Manager : Employee
{
public override decimal GetSalary() => 10000;
}

public class Developer : Employee
{
public override decimal GetSalary() => 8000;
}

// 多态调用
List<Employee> employees = new()
{
new Manager(),
new Developer(),
new Employee()
};

foreach (var emp in employees)
{
Console.WriteLine($"薪资: {emp.GetSalary()}");
}
// 输出:
// 薪资: 10000
// 薪资: 8000
// 薪资: 5000

11.7 类型检查与转换

is 运算符

1
2
3
4
5
6
7
8
9
10
11
12
Employee emp = new Manager();

if (emp is Manager)
{
Console.WriteLine("是经理");
}

// 模式匹配
if (emp is Manager m)
{
Console.WriteLine($"经理薪资: {m.GetSalary()}");
}

as 运算符

1
2
3
4
5
6
7
8
9
10
Employee emp = new Manager();

Manager manager = emp as Manager;
if (manager != null)
{
Console.WriteLine("转换成功");
}

// 失败返回 null
Developer dev = emp as Developer; // null

强制转换

1
2
3
4
Employee emp = new Manager();

Manager manager = (Manager)emp; // 成功
// Developer dev = (Developer)emp; // 抛出异常

11.8 继承最佳实践

1. 组合优于继承

1
2
3
4
5
6
7
8
9
10
11
12
13
// 不推荐
class Car : Engine { }

// 推荐
class Car
{
private Engine _engine;

public Car(Engine engine)
{
_engine = engine;
}
}

2. 使用抽象类定义模板

1
2
3
4
5
6
7
8
9
10
11
12
13
public abstract class ReportGenerator
{
public void Generate()
{
LoadData();
ProcessData();
SaveReport();
}

protected abstract void LoadData();
protected abstract void ProcessData();
protected virtual void SaveReport() { }
}

3. 避免深层继承

1
2
3
4
5
6
7
8
9
10
// 不推荐:继承层级过深
class A { }
class B : A { }
class C : B { }
class D : C { } // 难以维护

// 推荐:扁平化设计
interface IProcessable { }
class A : IProcessable { }
class B : IProcessable { }

11.9 本章小结

  • 继承使用 : 语法,支持单继承
  • base 调用基类构造函数和方法
  • virtual 声明虚方法,override 重写
  • new 隐藏基类方法
  • sealed 防止继承或重写
  • 多态允许基类引用调用派生类方法
  • is 检查类型,as 安全转换
  • 组合通常优于继承

练习题

  1. 创建 Vehicle 基类,派生 CarBike
  2. 实现多态:不同形状计算面积
  3. 使用 base 调用基类构造函数
  4. 以下代码输出什么?
    1
    2
    3
    4
    class A { public virtual void Show() => Console.WriteLine("A"); }
    class B : A { public override void Show() => Console.WriteLine("B"); }
    A obj = new B();
    obj.Show();
ByteFisher
分享编程技术 · 记录钓鱼乐趣
扫码关注
▸ 扫码关注 ◂
分享: