面向对象的三大特征
封装
隐藏内部实现,稳定外部接口->系统安全性进行提升
继承
子类继承父类成员,实现代码的复用->开发和维护效率提高
继承的使用
特点
-
从生活中理解继承
父母->儿女->孙辈
交通工具->飞机(直升飞机、战斗机、波音)、汽车(卡车、公交车、小轿车)、轮船
-
继承的特点
-
继承的顺序不可逆:继承从上往下依次继承,而不能逆序继承
-
继承的延续性:在继承的顺序中,下一级完整的具备上一级的属性和特征
-
为什么要使用继承
继承使用的必要性
-
提高代码的复用,减少代码的冗余
-
一处更新,处处更新
玩具厂商要实现一些玩具的程序
分析:所有的玩具都会有一些特征
-
属性:姓名、自身的颜色、类别
-
行为:跳舞、唱歌。。。
程序实现:
当人给玩具发送一个指令:这个玩具就会做出与他们对应的行为
如何实现继承
继承的步骤
-
抽象公共部分,放到一个特定的类中(父类、基类)
-
其他类(子类、派生类)只需要继承父类,即可拥有父类的特征(属性、方法)
-
根据子类的需求添加属于自己的特征和方法
具体实现
在子类后面使用继承符号":"继承父类
继承中的关键字
继承关系
Animal(父类)<<<<-----[Cat,Frog] (派生类)
概念
-
子类继承父类,父类派生子类
-
子类又叫派生类,父类又叫基类(超类)
-
子类继承父类成员,也可以有自己的独立程序
-
继承具有传递性:A->B;B->C C就具有A的特性
-
继承的单根性:一个类只能有一个父类,一个父类可以有任意多个子类
继承的必要条件
继承必须要符合关系:is-a的关系 【Cat is an Animal】
关键字
this关键字:可以访问自身也可以访问父类
base关键字:1.调用父类的构造函数 2.调用父类的属性和方法
和继承有关的访问修饰符
问题:如果父类中的某个成员只允许其子类访问应该如何实现
父类成员:
-
使用public修饰:所有的类都可以访问
-
使用private修饰:只有自己可以访问
-
使用protected修饰:仅允许子类访问,而不允许其他非子类访问
修饰符 | 类内部 | 子类 | 其他类 |
---|---|---|---|
public | 可以 | 可以 | 可以 |
private | 可以 | 不可以 | 不可以 |
protected | 可以 | 可以 | 不可以 |
多态
不同子类对同一消息,做出不同反应->系统扩展性增强
概念:
-
不同对象,接收相同消息,产生不同行为,称为多态
-
多态是由“聪明的”虚拟机自行决定的
实现:
使用继承实现多态
-
父类中必须有抽象方法或虚拟方法
-
子类必须重写父类中的抽象方法或选择重写父类中的虚拟方法
-
子类对象必须转成父类类型去使用
方法
-
方法的重载
-
构造重载
-
方法的重写:重写不能改变方法签名
里式替换原则
-
子类的对象能够替换其父类、
-
父类对象不能够替换子类
-
父类的方法都要在子类中实现或重写
is与as操作符
-
is主要用作检查对象是否是指定类型兼容,如果转换失败程序中断
-
as主要用作在兼容的引用类型之间执行转换,转换失败返回null
抽象
父类和子类相互转换
Cat cat = new Cat() { Name = "小黄", Type = AnimalType.Mammal }; Frog frog = new Frog() { Name = "小青", Type = AnimalType.Amphibious }; List<Animal> list = new List<Animal>(); //子类隐式转换为父类 list.Add(cat); list.Add(frog); foreach (Animal item in list) { //将父类强转成对应的子类 if (item is Cat) { ((Cat)item).Work(); } if (item is Frog) { ((Frog)item).Work(); } }
-
父类类型可以添加子类对象,子类自动转换成父类类型
-
将父类类型转成子类对象时,父类类型的对象必须强制转换成对应的子类对象,才能调用子类的独立成员
抽象类的使用
-
使用关键字abstract修饰的类称为抽象类
-
抽象类只是用来列举一个类所具有的行为,不能单独通过创建对象来使用
-
抽象类中可以有抽象成员,也可以没有任何抽象成员
-
抽象类不能是静态的或密封的
抽象方法的使用
-
抽象方法必须放在抽象类中
-
抽象方法使用关键字abstract修饰
-
抽象方法只是一个方法的声明,没有方法体
-
抽象方法仅表示一个应该具备的行为,具体的实现由子类完成
-
抽象方法在子类中必须被实现,使用关键字override重写
-
子类必须重写父类的所有抽象方法,除非子类本身也是抽象类
虚拟
问题:如果需要在父类中提供一个方法,该方法有自己的方法体,子类根据自身的需要再去决定是否重写该方法,这个方法重写不重写取决于子类自身的需求。
虚拟方法 | 抽象方法 |
---|---|
使用virtual | 使用abstract |
必须提供方法体和正常方法一致 | 不允许有方法体,只能有方法签名 |
子类可以选择重写也可不重写 | 子类必须重写抽象方法 |
除了密封类中都可以写 | 只能在抽象类中 |
访问修饰符
public
private
protected
internal
protected internal/protected internal
密封类
使用关键字:sealed
-
当一个类使用sealed修饰后,该类不能被继承
-
sealed对于保护知识产权起到一定作用,一定程度上限制别人二次开发
接口
什么是接口
应用接口之后,程序的可扩展性、可维护性会大大增强
接口的定义和实现
接口的定义类似于USB,主要作用是一共一个电源头
接口的实现类似于U盘或者USB线鼠标或者USB线键盘等等,主要作用是接口功能的体现
接口定义规范
-
使用关键字interface定义,接口类名通常使用“I”开头
-
接口中的属性、方法等,只是做一个声明,而没有任何实现
-
接口中的属性、方法等,默认都是public,不需要“画蛇添足”
接口的实践
问题:打印机对象:打印、复印、传真。市场流行的打印机:HP/SONY......
-
实现打印机接口
/// <summary> /// 多功能打印机接口 /// </summary> public interface IMultiPrinter { /// <summary> /// 打印功能 /// </summary> /// <param name="contents"></param> void Print(string contents); /// <summary> /// 复印功能 /// </summary> /// <param name="contents"></param> void Copy(string contents); /// <summary> /// 传真功能 /// </summary> /// <param name="contents"></param> void Fax(string contents); }
-
在具体对象中实现接口所提出的功能
class HPMultiPrinter : IMultiPrinter { public void Copy(string contents) { Console.WriteLine("惠普复印:"+contents); } public void Fax(string contents) { Console.WriteLine("惠普传真:" + contents); } public void Print(string contents) { Console.WriteLine("惠普打印:" + contents); } }
接口的特点
-
接口具有强制性,实现接口的类必须实现接口的所有成员
-
一个类既可以实现多个接口,也可以同时继承其他的类,前提是一般将继承的父类写在接口之前
-
类继承了多少个接口(间接继承、直接继承),对所有的接口都要进行实现
间接继承:A接口->B接口->C类
直接继承:A接口->C类,B接口->C类
接口的实践应用
-
接口提高团队成员并行开发项目的效率
-
接口的使用者只需要考虑接口的应用功能,而不用考虑接口的实现细节
-
接口的实现者只关心如何实现接口内部的细节,而不用考虑谁使用
-
-
接口能够提高系统的可维护性
当用户的需求改变时,只需要修改接口的实现,系统即可完成更新
接口的应用总结
-
接口的应用场合
-
如果某一个功能点需求变化比较多,应使用接口保证系统的可维护性
-
如果想实现团队成员的并行开发,可以使用接口来规范对象的使用
-
-
接口编写规范
-
接口成员只能是一个声明
-
实现接口的类必须全部实现接口中规定的属性、方法
-
-
特别说明
接口的使用不是必须的,要根据用户的需求来决定
接口实现多态
继承多态实现的条件
-
父类中必须有抽象方法或者虚拟方法
-
子类必须重写父类中的抽象方法或者虚方法
-
子类对象必须转换成父类去使用
接口多态实现的条件
-
一个接口必须被两个或两个以上类实现
-
接口实现类必须转成接口类型去使用
接口和抽象
抽象类 | 接口 | |
---|---|---|
不同点 | 用abstract定义 | 用interface定义 |
只能被继承一个 | 可以实现多个接口被继承 | |
非抽象派生类必须实现抽象方法 | 实现接口的类必须实现所有的成员 | |
需要使用override实现抽象方法 | 直接实现 | |
相似点 | 都不能直接实例化 | |
都包含未实现的方法 | ||
子类或“接口实现类”必须实现未实现的方法 |