.NET Core CSharp初级篇 1-6
本节内容为类的多态与继承
简介
终于讲到了面向对象三大特性中的两大特性——继承与多态。通过继承与多态,我们能很好的将类的拓展性发挥到了极致。在下面的内容讲解中,我们将从各个方面对继承和多态进行刨析。
继承
继承事实上是一个非常好理解的语法,在C#中实现继承使用A:B,表示A类继承B类。子类(一称为派生类)继承于父类(一称为基类)就好比孩子继承了父亲的一切,但是孩子总归是有自己的个性的,而父亲也有一些不会告诉孩子的事情。如果我们从之前的访问控制符这一部分进行理解的话,你可以这样描述这个“融洽”的父子关系。
假定有以下这个例子:塞巴斯蒂安·艾奎斯(父类)是一个欧洲宫廷的贵族,67岁,他是一个子爵,并且掌握了一个惊天大秘密不能告诉任何人,只能烂在肚子里。他育有一子名叫麦克·艾奎斯,由于塞巴斯蒂安·艾奎斯年老体弱,当家里需要钱的时候,他会让自己的儿子带上银行卡前往atm机取钱。儿子的车和他的车一模一样,每次儿子让管家开车的时候都必须说清楚:“我要开我父亲的车。”,或者:“今天我开我自己的车”。如果他没有说,那么管家会默认的取出儿子的车。他家还有一个大庄园闲置可以用于开发,只要父亲同意,那么儿子可以自由开发。
对于这个例子,你需要得出的结论是:
- 如果塞巴斯蒂安·艾奎斯(父类)没有出生,那么麦克·艾奎斯(子类)也不存在。(子类实例化时必定先调用父类构造方法)
- 对于塞巴斯蒂安·艾奎斯(父类),他的名字属于大家都可以知道的(public),谁都可以轻易的得到。但是想拥有这个名字,却只能是他的家族的人才可以(继承后才能获得父类的字段)。
- 对于前往ATM机取钱这件事,取款密码只可能告诉他的儿子,别人是不能得到的。(protected可以被子类访问,但是其余不可访问)
- 塞巴斯蒂安·艾奎斯(父类)知道一个秘密,这个秘密只有他本人才知道(private),包括他的儿子也不可能知晓(子类无法获取private)
- 因为父子俩的车一模一样,取车需要特别说明(子类和父类函数签名一致时,父类函数默认会隐藏,除非显式的说明)
- 大庄园是父亲的,但是可以被儿子取改造(父类函数指定为virtual时,子类可以重写父类函数)
通过这一些刨析,我认为你应该已经清楚了七八分继承的意思了。这里需要介绍一下我们的base关键字,base关键字在子类中体现为调用父类的方法。
特别的,你需要注意的是,C#对于类与类的继承只支持单继承,如果你试图实现多继承,你可以使用接口作为媒介和桥梁。
我们现在用一段代码演示完我们的继承,我们这个教程更多的是引导你去思考,而不是让你如同一些速成培训班出来的一样,没有独立的思考能力。
class Father
{
public Father()
{
Console.WriteLine("Father Method");
}
private string MSGSecret;
protected string BankSecret;
public string Name;
public string Car;
protected void test()
{
}
}
class Son:Father
{
public Son()
{
Console.WriteLine("Son Method");
}
//隐式的生成了这三个字段
//protected string BankSecret;
//public string Name;
//public string Car;
public string Car;
public void getCar()
{
base.Car;//父类
this.Car;//子类
base.test()//调用父类方法,如果签名不冲突,可以省略base
}
}
Son s = new Son();//思考一下这里会输出什么?
多态
多态是一个并不困难的东西,在继承和接口中我们讲到的重写其实就是多态性的一种类型了。之前我们简单的举过一个例子来说明多态:人和鲤鱼都是动物,但是人用肺进行呼吸,而鲤鱼用鳃进行呼吸。这个例子就很好的体现了多态。利用下面这段代码来解释吧。
class Animal
{
//通过抽象方法实现多态
abstract void Breathing();
//虚方法实现多态
virtual void Eat()
{
}
}
class Human:Animal
{
override void Breathing()
{
}
override void Eat()
{
}
}
class Fish:Animal
{
override void Breathing()
{
}
new void Eat()
{
}
}
Animal ah = new Human();
Animal af = new Fish();
Fish f = new Fish();
注意看最后几行,ah和af各属于Human和Fish的对象,但是当方法调用的时候,统一调用父类中的方法,并且加载子类中的重写和实现。
ah.Eat();//调用父类的Eat(),但是以Human类中的重写方法为实现
af.Eat();
f.Eat();
这三者的区别在哪里?事实上你只需要知道,多态性就是通过父类去管理子类,让子类遵循父类的规范。当子类使用从父类继承的方法的时候,是去调用父类的方法,但是使用子类的实现。特别的,如果你在方法中使用new修饰符,那么这个方法将会和父类毫无关系,就如这个单词的意思一样,这是一个新的函数,不是父类中的函数。现在你可以试着分析上述三个函数调用的各是哪个类中的方法。
多态最大的有点就是你可以通过一个基类或者接口去管理所有继承于他们的子类的函数方法,并且同一个函数可以有多种实现方法。
如果你使用接口和抽象类去实现多态,实现的方法也是一样的,只不过是基类型无法实例化。