第十节:多态、接口(之前简单说了一下多态(在第八节),这里详细说下多态吧,还有接口,装箱拆箱,有喜欢的小伙伴点个关注哟,共同学习进步!!!)
一、多态
多态:允许将子类类型的指针赋值给父类类型的指针。也就是同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
理解多态之前首先要对面向对象的里氏替换原则和开放封闭原则有所了解。
里氏替换原则(Liskov Substitution Principle):派生类(子类)对象能够替换其基类(超类)对象被使用。通俗一点的理解就是“子类是父类”,举个例子,“男人是人,人不一定是男人”,当需要一个父类类型的对象的时候可以给一个子类类型的对象;当需要一个子类类型对象的时候给一个父类类型对象是不可以的!
开放封闭原则(Open Closed Principle):封装变化、降低耦合,软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。因此,开放封闭原则主要体现在两个方面:对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。
对这两个原则有一定了解之后就能更好的理解多态。
多态的作用:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"。
多态性可以是静态的或动态的。
在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
二、接口
1)接口使用关键字Interface
2)接口中只能包含声明,不能有实现体
3)接口中能声明的类型:方法、属性、事件、索引器
使用场景:接口是为了解决不能继承多个基类的问题
接口的特征:
1)接口中不能包含字段
2)接口中的所有成员默认是public,不能再加访问修饰符
3)实现接口的任何类或者结构必须实现其所有成员的方法
4)接口不能被直接实例化,但是可以通过指向子类间接实例化
5)类或者结构可以实现多个接口,类可以继承基类并实现一个或者多个接口
接口的多重继承:
接口继承:
1)和类继承不一样,类的继承不仅是继承声明,而且继承具体实现,而接口继承只是继承声明;
2)接口可以从零个或者多个接口中继承,如果继承多个接口,接口之间用逗号分开,如果一个类继承多个接口,必须实现所有接口中的方法
什么时候用接口什么时候用抽象?
抽象:是对相同属性和方法的提炼而得
接口:是对相同行为不同实现方法的提炼
这里加一个案例吧:
using System;
namespace jiekou
{
public interface USB
{
//属性
float Type{ get; set;}
void Read();
}
public class Upan:USB
{
public void Read(){
Debug.Log ("U盘");
}
public float Type{ get; set;}
}
public class Ypan:USB
{
public void Read(){
Debug.Log ("硬盘");
}
public float Type{ get; set;}
}
}
装箱和拆箱:
1)执行装箱的过程中不可避免的要在堆内存上开辟内存空间,并将栈内存的值类型复制到申请的堆内存空间上,这个过程肯定会消耗内存和cpu的资源
2)拆箱的执行过程和装箱的操作过程正好相反,是将存储在堆上的引用类型转换为值类型并赋值给值类型变量
3)装箱和拆箱操作都会产生额外的消耗,占用了一定的CPU资源。所以在c#2.0之后引用泛型来减少装箱和拆箱的操作,从而节省内存和cpu资源消耗
例:
//第一条语句创建一个int类型变量age,并将值放在了栈内存空间上
int age = 18;
//第二条语句将age的值赋给了引用类型,这时,将值放在了堆内存空间上,这个将值类型包装为引用类型的过程,称为装箱
object refNum = age;
//拆箱操作
int num = (int)refNum;