多态
0. 多态
在继承关系的前提下,实例化出不同的对象,这些对象调用相同的方法,但是却表现出不停的行为,这就叫做多态。
在C#中体现多态的三种方式:虚方法、抽象类、接口。
1、虚方法
在父类中使用virtual关键字修饰的方法,就是虚方法。在子类中可以使用override关键字对该虚方法进行重写。
虚方法语法
父类: public virtual 返回值类型 方法名() { 方法体代码; } 子类: public override 返回值类型 方法名() { 方法体代码; }
使用细节
①将父类的方法标记为虚方法,就是在父类方法的返回值前加virtual关键字,表示这个方法可以被子类重写。
②子类重写父类方法,在子类的方法的返回值前加override关键字。
③父类中的虚方法,子类可以重写,也可以不重写。
④父类中用virtual修饰的方法,可以用于实现该方法共有的功能(比如初始化该方法),然后在子类重写该方法时,使用base关键字调用父类中的该方法。
2、抽象类
抽象方法
父类里面用virtual关键字修饰的方法叫做虚方法,子类可以使用override重新该虚方法,也可以不重写。.
虚方法还是有方法体的,当我们父类中的这个方法已经虚到完全无法确定方法体的时候,就可以使用另外一种形式来表现,这种形式叫抽象方法。
抽象方法语法
抽象方法的返回值类型前用关键字abstract修饰,且没有方法体。
抽象方法必须存在于抽象类中。
一个类如果定义为抽象类,那么里面可以没有抽象方法
一个类中如果有抽象方法,那么这个类必定是一个抽象类
抽象类不能被实例化,可以实例化非抽象子类的对象
抽象类的所有非抽象子类必须重写抽象类中的抽象方法
抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
3、接口
当抽象类中所有的方法都是抽象方法的时候,这个时候可以把这个抽象类用另外一种形式来表示,就是接口。
接口通常是作为扩展的功能来使用,是在原有的父子继承关系之外,单独实现的一种功能。
使用关键字interface创建的数据类型,没有class关键字,接口名一般使用“IXxx”这种方式进行书写,在一堆脚本中通过名字判断,I开头的一般都是接口。
interface IFly { void Fly(); } //Batmobile继承Car类,实现IFly接口 class Batmobile:Car,IFly { public Batmobile(string brand):base(brand){} public void Fly() { Console.WriteLine("{0}在飞行",base.brand); } }
接口的语法特点:
1、接口中不能包含字段,可以包含:行为【方法,属性,索引器,事件】
在没有字段的情况下,如何使属性?
1.常规属性
先定义一个私有的字段,然后在为这个私有字段封装一个公开的属性,在属性中实现get和set两个方法,这种方式叫做常规属性。
当我们使用常规属性的时候,可以在get和set方法中,编写逻辑代码对取值和赋值进行逻辑的校验。
这种方式是我们之前一直在使用的方式。
2.自动属性
在某些情况下,属性的get和set只是完成字段的取值和赋值操作,而不包含任何附加的逻辑代码,这个时候可以使用自动属性。
例如:
public int Age { get; set; }
当我们使用自动属性的时候,就不需要再写对应的字段了,C#编译器会自动给我们的自动属性提供一个对应的字段。
注意:
在接口中使用属性,就要写自动属性的格式,因为接口中不支持字段。
2、接口中的所有成员不能加任何访问修饰符,全部默认公有public
3、接口中的所有成员不能有实现,全部默认抽象的(不能有方法体)
4、实现类实现接口用“:”与继承相同
5、实现类实现可以实现多个接口,且每个接口中所有的成员必须都实现(即实现类可以继承多个接口,不同于类只能继承一个)
6、接口中的成员在实现类中以public的方式实现(除显式实现)
7、接口的引用可以指向实现类的对象 接口 obj=new 实现类()
注意事项:
1、类继承接口 Class A : interface B,interface C类需要实现继承接口中所有的方法,支持多继承
2、接口继承接口 interface A :interface B,interface C接口不能实现继承接口的任何方法,支持多继承
3、struct结构体可以继承接口,但是不能继承类
类实现接口的方式:
1、隐式实现
public 数据类型 接口方法(){方法体}
2、显示实现(非常规用法,很少用,了解一下就好)
数据类型 接口名.接口方法(){方法体}
当成私有方法使用,外部无法访问,除非 接口 A = new 继承类,此时A可以在外部访问。
显示实现的作用。
1、解决接口中的成员对实现类不适用的问题。
即:接口中有若干方法该类不需要实现,使用显示实现在外部写代码时将不会显示。一定程度上减少代码污染,
2、解决多接口实现时的二义性问题(用的更少)
即:接口A中有跑步的方法,接口B中也有跑步的方法,当一个类同时继承的时候,系统不知道想实现哪个接口,此时可以使用显示实现,不用也不会报错。
4、虚方法抽象类接口对比
语法格式对比:
1、父类中存在虚方法,父类是可以实例化对象的,创建的对象调用时,调用虚方法,如果子类重写了方法,那么子类对象调用重写后的方法;
使用场景对比:
虚方法:父类中的个别方法用虚方法实现,然后允许子类在有需要的情况下重写这些虚方法。
抽象类:父类定义一系列的规范,子类去把父类里面定义的这些规范全部实现。
接口:是一种功能的扩展,是在原有的类的继承关系以外的新功能的扩展。