虚方法和抽象方法以及多态的本质(里氏替换原则)!

来源:互联网 发布:ubuntu 界面应用 编辑:程序博客网 时间:2024/04/28 05:07

函数重写:被重写的父类函数必须是【虚方法或抽象方法】

函数必须相同(返回值、函数名、参数列表)

重写的函数的修饰符必须等于父类

重写的函数的返回值类型等于父类返回值

构造函数无法重写(因为构造函数无法继承)


虚方法,多态

多态两种 表现形式:用父类做参数;用父类做返回值。

多态就是对象可以表现多个类型的能力。

多态就是指不同对象收到相同消息时,会产生不同行为同一个类在不同的场合下表现出不同的行为特征。

多态的作用:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。

1.Person p=new Person(); Student s=new Student();  子类对象赋值给父类,是符合里氏替换原则的。(编译的时候,CLR会自动检查看对象s的类是否有继承p对象的类,如果有,则允许赋值,如果没有,则报异常)

父类对象不能直接赋值给子类(编译的时候CLR检查到p得类没有继承s的类,所以报异常);

从人类的思维的角度看:子类拥有父类所没有的成员,如果将父类转成子类,意味着子类的成员不能从父类获值。

不能用父类来实例化子类的变量的原因:因为声明的子类变量语法上是可以点出子类成员,但是父类对象里没有包含子类成员,那么根本就没法访问了。微软为了杜绝这种情况,直接编译报错。

=右边所创建的成员,少于=左边所允许访问的成员。

指向子类对象的父类变量可以强转成子类变量  通过的原因:尽管p1是父类变量,但是p1里保存的指针指向的堆空间里是子类对象。

=左边:叫声明变量,程序员可以按照变量的类型来写代码(可以.出来)

isas

is关键字:可以用来判断引用类型的对象,如果是某个类,则返回true,否则返回false;如果用来判断值类型,则永远返回false

as关键字:(一般用来指向子类对象的父类变量转成子类变量)用在引用类型间转换,如果转换失败则返回null,但不会报错。

里氏替换原则 子类可以实例化父类(子类可以替换父类的位置)

讲父类转成子类需要强制转换,强制转换的时候 必须有直接继承关系才能完成强转。否则会出异常

当我们new 一个子类对象时,父类里被重写的方法就不存在了,对象中只有子类的重写方法。

多态:(由 里氏替换原则 和 方法重写 构成)

//父类  p = new 子类();

//多态 : 

//1.声明一个父类 变量,不关心  具体创建的 对象 是哪个子类

//2.父类变量 调用 了一个  被子类重写的方法,那么这个方法的调用行为 就叫做多态。

Person duotai = new Girl();

duotai.SayHi();//一种 形态,多种表现形式(具体是通过 子类 重写父类 方法 来实现的)

开闭原则:设计原则。

   7.1 对修改关闭:一旦代码“写完”,就不应该再修改源代码。

   7.2 对扩展开放:即使代码“写完”,但只要通过修改配置文件,赋值新的程序集到指定位置等方式,就可以 为程序添加新的功能。

抽象方法

1.抽象类与抽象方法用abstract修饰。

2.抽象类和接口不能被new 出来,抽象方法不能有方法体。

3.抽象类和抽象方法存在的意义:

  1.向子类形成一个规范(子类必须重写父类的抽象方法,除非子类也是抽象类。)

  2.根本目的,是为了实现多态

4.尽管抽象类不能被new 但它也可以有构造函数进行成员变量的初始化,只不过由子类构造函数调用

抽象方法不能使用private,因为抽象类的私有成员既不能被抽象类本身访问(不能new抽象类对象),又不能被子类继承,所以没有存在的价值了。为了避免这种浪费内存的情况,C#规定在抽象类中不能使用private修饰

6.模板模式

模板模式:抽象方法,没有具体的实现,有一个按照流程调用的方法。

虚方法和抽象方法的区别:

1.虚方法必须有实现,抽象方法必须没有实现

2.抽象方法必须在抽象类中声明,虚方法可以出现在抽象类中

3.抽象方法必须在子类中重写,虚方法可以被重写

Sealed密封类:不能被子类继承还可以修饰重写方法。

1.类和类的关系:继承

2.类的继承关系(is a:子类就是父类

隐藏基类:当子类和父类里有同名的,但是没有重写的方法时,那么创建子类时,子类对象中同时包含子类和父类的此同名方法。

  1.1此时,如果声明的是子类,就执行子类的同名方法。

  1.2此时,如果声明的是子类,就执行父类的同名方法。

2.当子类和父类有同名方法时,默认就是用了隐式隐藏父类方法的new关键字。如果和上面一样

多态表现形式:里氏替换原则,具体的代码使用:

1.方法将父类当成返回值,具体return的是某个子类对象。

2.方法将父类当成形参,具体传入的实参是某个子类对象。

4.常量:1.不能在任何地方修改  2.只能在初始化的时候赋值

  只读变量:可以在构造函数被修改