继承和多态 复习

 

里氏替换原则(lsp)

•Person p = new Teacher();

子类可以隐式的转换成父类.

•Teacher t=(Teacher)p;

父类必须强转成子类

•简单工厂

•is和as

–typeA is type B 仅判断A是否是B类型,或者 是否是B类型的子类

–typeA as TypeB 先判断,再转换(如果转换失败,则直接给null值,但不会报错)

多态——隐藏基类方法与多态的实现

•子类可以有与父类方法名相同的方法

–参数不同(重载)

–参数相同(隐藏基类方法)

•子类可以重写父类方法

–虚方法 virtual

–重写方法 override

–重写基类方法一样可以调用基类方法(基类方法仍然存在于对象中,只是不能访问而已)

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

虚方法virtual

•虚方法可以给父类中的方法一个实现,比如ToString()方法

•虚方法必须有实现部分,抽象方法没有提供实现部分

•问:员工类、部门经理类(员工有上班打卡的方法,考虑该方法是abstract还是virtual的)

 

 

虚方法和抽象方法的区别

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

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

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

实现多态的主要手段

1.虚方法virtual

2.抽象方法abstract

3.接口。

关于虚方法需要注意的几点:

1.父类中如果有方法需要让子类重写,则可以将该方法标记为virtual

2.虚方法在父类中必须有实现,哪怕是空实现。

3.虚方法子类可以重写(override),也可以不重写。

 

多态——抽象方法与抽象类

 

•抽象类与抽象方法由abstract修饰

•abstract的使用注意

–抽象方法没有方法体

–抽象成员只能存在于抽象类中

–抽象类可以有非抽象成员

–抽象类的派生类必须实现抽象方法体

–抽象类只能用作基类,无法实例化

多态:为了程序的可扩展性。

•开放封闭原则(对修改封闭,对扩展开放。)

•ToString()方法

•多态就是指不同对象收到相同消息时,会产生不同行为

–同一个类在不同的场合下表现出不同的行为特征

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

 

•里氏替换原则

–父类引用指向子类对象Person p=new Chinese();

–父类对象不能够替换子类Chinese c=new Person();(×)

•is-a:可以用来验证继承关系中是否合理。(can do接口*)

•if(obj is 类型A)//obj是父类类型对象,”类型A”是子类类型。

•关键字as (类型转换)、 is

=======================as====================

//如果转换成功则将结果赋值给cn变量,

//如果转换失败也不报错,会将null值赋值给cn;

//最好在转换后,加一个cn是否为null的验证。

Chinese cn = per as Chinese;

if (cn!=null)

{

//做一些事情

}

//如果转换失败会报错!!!

Chinese cn1 = (Chinese)per;

============================================================================

/// <summary>

/// 父类类型作为参数的一种多态

/// </summary>

/// <param name="per"></param>

static void RenKouDengji(Person per)

{

per.DengJi();

}

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

==============================================

//如果转换失败报异常

//Chinese newcn = (Chinese)per;

// Chinese newcn = per as Chinese;

////类型转换,如果转换成功,则newcn中为转换后的结果

////如果转换失败,则newcn为null

Chinese newcn = per as Chinese;

 

抽象类abstract

•抽象类不能被实例化。

•抽象类存在的意义:1.抽象类不能被实例化,只能被其他类继承2.继承抽象类的子类必须把抽象类中的所有抽象成员都重写(实现)(除非子类也是抽象类。)3.抽象类就是为了重写→多态。

•什么是抽象类(光说不做)

–不能被实例化的类(不能new)

•抽象类的特点

–见备注

•如:我们的算法父类其实没必要有具体代码实现,可以改成抽象类。

•练习1:动物animal   都有吃eat和叫bark的方法,狗dog和猫cat叫的方法不一样

•练习2:计算形状Shape(圆Circle,矩形Square ,正方形Rectangle)的面积、周长

 

//1.需要用abstract关键字标记

//2.抽象方法不能有任何方法实现。

//3.抽象成员必须包含在抽象类中。

//4.由于抽象成员没有任何实现,所以子类必须将抽象成员重写。

//5.抽象类不能实例化,既然不能实例化,

//抽象类的作用:抽象类的作用就是为了让子类继承。

//6.抽象类中可以包括抽象成员,可以包括有具体代码的成员。

//7. 还有抽象方法不能用static修饰

public abstract void ShowNationality();

做网站的公司(抽象类) 你给我活我去开发网站,但是网站需要一部分flash,我公司力都是程序员(抽象类中有实现的方法)。没人会做flash(抽象方法),于是我把做flash这部分工作给其它公司去做(重写抽象方法的类)

抽象类定义的是公共的实现和能力

抽象类不能被实例化

抽象类为子类提供所需要的成员

抽象类中的成员既可以有实现也可以无实现

抽象类必须由其子类实现它的抽象成员(除非子类也是抽象类)

一个类只能继承一个抽象类(类的单根继承性)

抽象方法(成员)不能有实现,必须被子类重写override(除非子类也是抽象类)

抽象方法(成员)的只能出现在抽象类中。

多态性的含义:使得能够利用基类的指针来引用不同子类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作。

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

知识点补充1:关于抽象类知识点补充

•抽象类中的抽象成员不能使用private访问修饰符,可以使用其他访问修饰符。

•常见问题:

–当鼠标放到父类上时,没有自动提示“必须实现父类中的抽象方法”,原因可能是父类不是abstract或,父类中没有abstract成员。

什么时候用虚方法?什么时候用抽象方法?

虚方法:

1.父类中必须有实现。

2.子类中可以不重写。

3.虚方法可以在普通类中。(有序方法的类是可以(可能)被实例化的。)

抽象法:

1.父类中不能有任何实现。

2.子类中必须重写(除非:子类也是一个抽象类。)

3.抽象方法必须在抽象类中。

员工类:

Employee

{

void DaKa();

}

Manager:Employee

{

override void DaKa(){}

}

//什么时候用虚方法:

1.父类本身需要被实例化

2.这个方法在父类中有实现的必要(有意义)(方法有默认的实现。)

//什么时候用抽象方法:

1.在当前系统中,父类绝对不会被实例化。Person p=new Person();

2.在父类中不知道如何去实现这个方法(没有默认的实现。)


 

多态——小结

•几种建立多态的方式

–用父类实现多态

–用抽象类实现多态

–用接口实现多态

•版本控制

–需要重写方法时使用override关键字

 

new关键字

new关键字:

1.表示在子类中隐藏了从父类继承过来的那个虚方法。子类类型 obj=new 子类类型();

2.用new标记的方法是子类中的一个全新的方法,与从父类中继承过来的方法没有一点关系(截断了)

3.不能多态了。

//在子类中使用new关键字标记方法的执行结果:

Person person = new American();

person.SayHello(); //调用的父类的SayHello()方法

//==================================

American us = new American();

us.SayHello();//调用的是子类的SayHello()方法。

======================

class Chinese : Person

{

//new关键字将父类中继承过来的SayHello()隐藏了。

//而下面的这个SayHello()与父类中的SayHello()没有任何半毛钱关系。

//这个不叫方法重写。

//当前类中没有重写父类中的SayHello()方法。

public new void SayHello()

{

Console.WriteLine("子类中的SayHello.");

}

}

 

 

接口:规则-完全是为了约束(统一)类的行为

•完全一种约定

•接口就是用来实现的

•语法:

[访问修饰符] interface 接口名

{

// 接口成员定义

}

•接口只有方法、属性、索引和事件的声明

•接口是用来实现的,所有成员默认为public

接口的实现

•接口的实现类似于继承

–补充方法体

•接口是“多继承”

–由于“多继承”,无法保证方法重名的问题

–可以显式实现接口的成员

•<接口名>.方法名(){ /* 方法体 */ }

–显式实现的接口成员必须由接口对象来调用

静态方法和实例方法(定义和调用)

image
原文地址:https://www.cnblogs.com/iceicebaby/p/2795092.html