继承与多态
继承与多态
一、继承
子类继承父类,通过在类后面加冒号来继承某个类A:B。
继承的作用:一旦形成继承关系后,子类的对象就能够使用父类中的公共属性和方法函数
㈠继承关系中的方法隐藏、虚(抽象)方法、虚(抽象)属性
⒈隐藏:
当子类中写了跟父类同名同参数的方法之后,子类创建对象后,调用的是该子类里面的同名方法。
⒉父类变量与子类变量之间转换的规则:
⑴可以定义一个父类变量,引用子类对象(若有函数重写,存储了子类对象的父类变量调用同名方法时只能访问父类的方法,无法调用原先子类重写的方法以及特有的成员);
⑵利用强制转换可以让一个子类变量引用被父类变量引用的子类变量?(可以访问子类重写的同名方法和其他特有成员);
⑶直接通过父类的构造函数构建的对象, 不能存储在子类变量里。
由此可以得出一个结论:
当分别位于父类和子类的两个方法完全一样时,调用哪个方法由对象变量的类型决定。
namespace ConsoleApplication1 { public class Fulei { public void shuohua() { Console.WriteLine("我是父类的方法"); } } } namespace ConsoleApplication1 { public class Zilei:Fulei { public void shuohua() { Console.WriteLine("我是子类的方法"); } } } static void Main(string[] args) { //子类调用父类的方法 Zilei1 b = new Zilei1(); b.shuohua(); //调用子类的同名方法 Zilei a = new Zilei(); a.shuohua(); //定义一个父类变量引用子类实例 Fulei c = a; c.shuohua(); //子类变量引用被父类变量引用的子类实例 Zilei d = (Zilei)c; d.shuohua(); }
⒊重写与虚方法
上述隐藏的示例中,由于子类隐藏了父类的同名方法,如果不进行强制转换就无法通过父类变量直接调用子类的同名方法,哪怕父类变量引用的是子类对象。
这是不太合理的。我们希望每个对象都只干自己职责之内的事,即如果父类变量引用的是子类对象,则调用的就是子类定义的方法,而如果父类变量引用的就是父类对象,则调用的是父类定义的方法。这就是说,希望每个对象都“各人自扫门前雪,莫管他人瓦上霜”。
虚方法:在父类同名方法前加关键字override,表明这是一个虚方法,子类可以重写此方法:即在子类同名方法前加关键字override,表明对父类同名方法进行了重写。
必须在子类当中通过override进行重写覆盖来实现方法内容
虚方法的作用:如果在父类中与子类的同名方法前面加virtual, 在子类中同名方法前面的加override之后,当用父类变量引用子类对象,通过父类变量调用的同名方法是子类的方法,实现了子类对象对父类同名方法的覆盖。
public class Fulei { public virtual void shuohua() { Console.WriteLine("我是父类的方法"); } } public class Zilei:Fulei { public override void shuohua() { Console.WriteLine("我是子类的方法"); } } static void Main(string[] args) { //创建父类对象 Fulei a = new Fulei(); a.shuohua(); //创建子类对象 Zilei b = new Zilei(); b.shuohua(); //父类变量引用子类对象 a = b; a.shuohua(); }
子类的方法可以与父类的方法构成重载(很少用)。
4.抽象属性:
同抽象方法一样,需要重写。
如果没有字段,属性自己也可以默认自己是字段,赋值和取值(看来,属性可以脱离字段,独当一面)。
㈡抽象类与接口:
1.抽象类
在一个类前面加上“abstract”关键字,此类就成为了抽象类。
对应的,一个方法前面加上“abstract ”关键字,此方法就成为了抽象方法。
抽象类不能创建对象(实例),只能用作继承关系中的父类 ,其他用法和普通的类的继承用法相同。
抽象方法不能有实现代码,在函数名后直接跟一个分号。
如果不实现,那么就默认这个子类也变成了一个抽象类,
必须再在其他地方去继承实现它才可以。
public abstract class Fl { public abstract void shuohua(); } public class Zl:Fl { //实现抽象类的抽象方法 public override void shuohua() { Console.WriteLine("我是子类的方法"); } } static void Main(string[] args) { //创建子类对象 Zl a = new Zl(); a.shuohua(); //抽象类变量引用子类对象 Fl b = a; b.shuohua(); }
2.怎样添加一个接口?
添加->类->接口
一个类只能继承一个父类,但一个类可以继承多个接口
接口不能创建自己的实例,接口中不能写字段、属性
接口里的方法怎样实现?
接口里的方法不能有内容,必须要在子类里面的方法里写上内容;
定义一个接口类型的变量,存储一个子类对象;
通过该接口类型的变量,调用接口方法。
类型转换:
子类的实例可以放在转换为接口类型的变量里;
存于接口变量的子类实例可以强制转换回原先的子类类型(无法调用接口方法);
如果该类继承多个接口,那么在讲类的实例放在某个接口类型的变量中后,该实例只能转换成该子类类型变量里和该接口类型(利用强制转化),不能放在其他接口类型的变量里。
二、多态
继承于父类的子类有自己特有的成员。
小知识点:
创建一个子类对象,将它存储在子类变量和父类变量里,其实只有一个子类对象,子类变量和父类变量引用的是同一个地址,同一个对象。
修饰符:
protected:当前类及子类可以访问,注意子类创建的对象不能访问。
internal(类的默认访问权限):当前命名空间(类的默认命名空间)内可用。
利用msdn查找C#中一个函数的用法:
在百度搜索框中输入:函数名 msdn
中间与msdn中有一个空格
例如:
parse msdn
window.open msdn