Files
My-Notes/笔记/CSharp/核心/继承.md
T
2026-06-21 09:51:55 +08:00

287 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 继承
概念:
继承是面向对象三大特性之一
可以让一个类在已有类的基础上继续扩展
被继承的类一般叫==父类 / 基类(base class==
继承别人的类一般叫==子类 / 派生类(derived class==
通常用法:
1. 提取多个类的共同内容,减少重复代码
2. 表达“==is-a==”关系
3. 让子类在父类基础上增加自己的成员和功能
语法:
```csharp
class 子类名 : 父类名
{
}
```
案例:
```csharp
class Animal
{
public string name;
protected int age;
public Animal(string name)
{
this.name = name;
}
public void Speak()
{
Console.WriteLine("动物发出声音");
}
}
class Dog : Animal
{
public Dog(string name, int age) : base(name)
{
this.age = age;
}
public void Bark()
{
Console.WriteLine(name);
Console.WriteLine(age);
Console.WriteLine("汪汪");
}
}
Dog d = new Dog("旺财", 3);
d.Speak();
d.Bark();
```
`Dog : Animal` 就表示 `Dog` 继承了 `Animal`
注意:
1. ==C# 的类只能直接继承一个父类==,也就是单继承
2. 继承可以传递,A 继承 B,B 继承 C,那么 A 也会拥有 C 中可继承的成员
3. ==构造函数不会被继承==,子类只是可以调用父类构造函数
4. 父类的 `private` 成员子类==不能直接访问==,想给子类用一般写 `protected`
5. 结构体 `struct` ==不支持继承类==,但可以实现接口
6. 子类对象本质上也是父类对象的一种,所以继承是后面学[[多态vob|多态]]和[[里氏替换原则]]的基础
----
# 继承中的构造函数
概念:
继承里最容易混淆的一点就是==“子类会继承父类成员,但不会继承父类构造函数”==
当你 `new` 一个子类对象时,不只是创建“子类自己的部分”,还要先把==父类那一部分==初始化好
所以子类构造函数最终一定会调用某个父类构造函数
通常用法:
1. 让父类负责初始化“大家共有”的数据
2. 让子类只负责补充自己的初始化逻辑
3. 保证对象创建出来时就是完整、可用的状态
核心规则:
1. ==父类构造函数不会被继承==
2. ==子类构造函数最终一定会调用某个父类构造函数==
3. 如果子类没有显式写 `: base(...)`,编译器会尝试补一个 `: base()`
4. 如果父类没有无参构造函数,子类就必须显式写 `: base(...)`
5. 构造函数体的执行顺序可以先记成:==先父类,后子类==
案例1:显式调用父类构造函数
```csharp
class Person
{
public string Name;
public Person(string name)
{
Name = name;
Console.WriteLine("Person构造");
}
}
class Student : Person
{
public int Score;
public Student(string name, int score) : base(name)
{
Score = score;
Console.WriteLine("Student构造");
}
}
Student s = new Student("小明", 100);
```
执行理解:
1. 先执行 `Person(string name)`
2. 再执行 `Student(string name, int score)` 的函数体
案例2:父类有无参构造函数时,可以省略 `base()`
```csharp
class Animal
{
public Animal()
{
Console.WriteLine("Animal构造");
}
}
class Dog : Animal
{
public Dog()
{
Console.WriteLine("Dog构造");
}
}
Dog d = new Dog();
```
↑ 这里虽然没写 `: base()`,但编译器会默认帮你补上
案例3:父类没有无参构造函数时,子类必须显式写 `base(...)`
```csharp
class Animal
{
public string Name;
public Animal(string name)
{
Name = name;
}
}
class Dog : Animal
{
public Dog(string name) : base(name)
{
}
}
```
错误示意:
```csharp
class Dog : Animal
{
public Dog()
{
}
}
```
↑ 这时会报错,因为编译器默认想调用 `base()`,但父类根本没有无参构造函数
案例4:子类构造函数之间也可以先用 `this(...)` 串起来
```csharp
class Animal
{
public string Name;
public Animal(string name)
{
Name = name;
}
}
class Dog : Animal
{
public int Age;
public Dog() : this("默认小狗", 0)
{
}
public Dog(string name, int age) : base(name)
{
Age = age;
}
}
```
理解:
`Dog()` 没有直接 `base(name)`,而是先调用同类里的 `Dog(string name, int age)`
然后再由那个构造函数去调用 `base(name)`
所以最终调用链还是会到父类构造函数
注意:
1. 一个构造函数初始化器里==只能写一个==,也就是写了 `this(...)` 就不能再写 `base(...)`
2.`this(...)` 调到的另一个构造函数里,仍然可以写 `base(...)`
3. 不要在子类里重复初始化父类已经负责的数据,父类自己的数据最好交给父类构造函数处理
4. 初学阶段先牢牢记住:==创建子类对象时,一定先把父类部分构造好==
----
# base关键字
概念:
`base` 用来在==子类内部==访问父类成员
最常见的用途就是调用父类构造函数
通常用法:
1. 在子类构造函数中调用父类构造函数
2. 在子类方法中访问父类同名成员或父类方法
语法:
```csharp
class Dog : Animal
{
public Dog(string name) : base(name)
{
}
}
```
调用父类成员:
```csharp
base.父类成员名
```
案例:
```csharp
class Father
{
public string name;
public Father(string name)
{
this.name = name;
}
public void Say()
{
Console.WriteLine("我是父类");
}
}
class Son : Father
{
public Son(string name) : base(name)
{
}
public void Test()
{
base.Say();
Console.WriteLine(base.name);
}
}
Son s = new Son("小李");
s.Test();
```
`base(name)` 是先调用父类构造函数,`base.Say()` 是调用父类方法
注意:
1. `base` 只能在==实例构造函数、实例方法、实例属性访问器==里用
2. ==静态方法里不能用 `base`==
3. 如果父类没有无参构造函数,子类通常就要显式写 `: base(...)`
4. `base` 是访问父类成员,不是创建一个新的父类对象
----
引用:
1. Microsoft Learn: [Inheritance - derive types to create more specialized behavior](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/object-oriented/inheritance)
2. Microsoft Learn: [Inheritance in C# and .NET](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/inheritance)
3. Microsoft Learn: [Constructors (C# Programming Guide)](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/constructors)
4. Microsoft Learn: [Using constructors](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/using-constructors)
5. Microsoft Learn: [base (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/base)
6. Microsoft Learn: [protected (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/protected)
#继承
#核心