# 继承
概念：
	继承是面向对象三大特性之一
	可以让一个类在已有类的基础上继续扩展
	被继承的类一般叫==父类 / 基类（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)

#继承
#核心
