home commit with new plugins
This commit is contained in:
+168
-25
@@ -11,28 +11,28 @@
|
||||
3. 让子类在父类基础上增加自己的成员和功能
|
||||
|
||||
语法:
|
||||
```Csharp
|
||||
```csharp
|
||||
class 子类名 : 父类名
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
```csharp
|
||||
class Animal
|
||||
{
|
||||
public string name;
|
||||
protected int age;
|
||||
|
||||
|
||||
public Animal(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public void Speak()
|
||||
{
|
||||
cw("动物发出声音");
|
||||
Console.WriteLine("动物发出声音");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +42,12 @@ class Dog : Animal
|
||||
{
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
|
||||
public void Bark()
|
||||
{
|
||||
cw(name);
|
||||
cw(age);
|
||||
cw("汪汪");
|
||||
Console.WriteLine(name);
|
||||
Console.WriteLine(age);
|
||||
Console.WriteLine("汪汪");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,11 +59,152 @@ d.Bark();
|
||||
|
||||
注意:
|
||||
1. ==C# 的类只能直接继承一个父类==,也就是单继承
|
||||
2. 继承是可以传递的,A 继承 B,B 继承 C,那么 A 也会继承到 C 的可用成员
|
||||
2. 继承可以传递,A 继承 B,B 继承 C,那么 A 也会拥有 C 中可继承的成员
|
||||
3. ==构造函数不会被继承==,子类只是可以调用父类构造函数
|
||||
4. 父类的 `private` 成员子类==不能直接访问==,想给子类用一般写 `protected`
|
||||
5. 结构体 `struct` ==不支持继承类==,但可以实现接口
|
||||
6. 子类对象本质上也是父类对象的一种,所以继承是后面学[[多态vob|多态]]的基础
|
||||
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关键字
|
||||
@@ -76,34 +217,35 @@ d.Bark();
|
||||
2. 在子类方法中访问父类同名成员或父类方法
|
||||
|
||||
语法:
|
||||
```Csharp
|
||||
```csharp
|
||||
class Dog : Animal
|
||||
{
|
||||
public Dog(string name) : base(name)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
调用父类成员:
|
||||
```Csharp
|
||||
```csharp
|
||||
base.父类成员名
|
||||
```
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
```csharp
|
||||
class Father
|
||||
{
|
||||
public string name;
|
||||
|
||||
|
||||
public Father(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public void Say()
|
||||
{
|
||||
cw("我是父类");
|
||||
Console.WriteLine("我是父类");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,13 +253,12 @@ class Son : Father
|
||||
{
|
||||
public Son(string name) : base(name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void Test()
|
||||
{
|
||||
base.Say();
|
||||
cw(base.name);
|
||||
Console.WriteLine(base.name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,14 +271,16 @@ s.Test();
|
||||
1. `base` 只能在==实例构造函数、实例方法、实例属性访问器==里用
|
||||
2. ==静态方法里不能用 `base`==
|
||||
3. 如果父类没有无参构造函数,子类通常就要显式写 `: base(...)`
|
||||
4. `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: [base (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/base)
|
||||
4. Microsoft Learn: [protected (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/protected)
|
||||
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)
|
||||
|
||||
#继承
|
||||
#核心
|
||||
|
||||
Reference in New Issue
Block a user