里氏替换原则
子类可以替换父类的位置,并且程序的功能不受影响
因为父类有的成员 子类对象都有,所以程序的功能不受影响
1、父类变量指向子类对象
2、当父类变量指向子类对象的时候 通过这个变量来调用同名的方法的时候,会调用父类的同名方法,,上图中的类型指针指的时父类的方法表,而这个指针是由变量的类型决定,上图中Person p类型是Person,所以指向Person的方法表
3、当1个父类变量指向子类的对象的时候,只能通过这个父类的对象调用父类对象的成员,子类对象独有的成员调用不到,为了多态
注:Student s2=new Person()(不行,不符合自动转换条件:数据类型兼容,目标类型大于源类型),但可以强制转换,语法上没错误,但是运行可能出现错误Person p1=new Person(); Student s2=(Student)p1;(强制转换条件(有可能丢失精度):数据类型兼容)例如Person p1=new Student (); Student s2=(Student)p1(这样转换才可以),强制转换的时候,除非父类变量确实指向了1个子类的对象才可以成功将这个父类变量对象转换为一个子类对象,Person p1除非p1确实指向Student对象,否则不能把p1转换为Student对象
Is关键字
用来判断指定的变量是否指定的类型,返回的时true 和 false
P is Student()//返回时真
P is object//返回时真
子类对象永远是父类类型
当父类变量指向子类对象的时候,这个父类变量是1个父类类型也是一个子类类型
没有继承关系的时候,is返回时false
Int i=12
i is int //true
i is double //false
is 只适合引用类型的判断
as关键字
as转换失败不报异常返回null
变量的类型决定可以调用那些成员,无论你指向那一个对象上图中s可以调用Student里面的成员
装箱与 拆箱
int i=12;//将值类型转换为引用类型
object o =i;//引用与值类型转换
int j=(int)o
j=11
//i还是12
//装箱过程:
1、在堆中分配好内存,值类型各个字段所需要的内存量+额外成员
2、值类型的字段复制到新分配的内存
3、返回地址
装箱过程很耗性能,尽量避免装箱操作
拆箱:将引用类型转换为值类型
1、 获取已装箱的对象的各个字段的地址(发生拆箱操作)
一般情况下,紧跟拆箱后 将这些字段的值复制到栈空间的值类型中去
拆箱的效率比装箱高 因为拆箱不需要复制字段的值
用+号连接字符串的时候,内部会调用string.Concat方法将每一个串作为参数传递到这个方法中
方法重写
被virtual修饰的方法叫做虚方法
虚方法可以被子类重写,可以通过override关键字重写父类的虚方法
Public override void SayHi()
当父类变量指向子类对象的时候并且子类重写,调用的时子类重写的方法,如果子类没有重写调用的时父类的方法
Person p1=new Sturdent();
为了多态
开闭原则:对扩展开放,对修改关闭
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 多态 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //多态好处:对扩展开放,对修改关闭 14 string uins = "-"; 15 JiSuan js = null; 16 switch (uins) 17 { 18 case "+": 19 js = new Jia(1, 3); 20 break; 21 case "-": 22 js = new Jian(1, 3); 23 break; 24 case "*": 25 js = new Cheng(1, 3); 26 break; 27 case "/": 28 js = new Chu(6, 3); 29 break; 30 } 31 Console.WriteLine(js.GetRes()); 32 Console.ReadKey(); 33 } 34 } 35 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 多态 8 { 9 class JiSuan 10 { 11 public int Num1 = 0; 12 public int Num2 = 0; 13 public JiSuan(int n1, int n2) 14 { 15 Num1 = n1; 16 Num2 = n2; 17 } 18 19 public virtual int GetRes() 20 { 21 return 0; 22 } 23 24 } 25 class Jia:JiSuan 26 { 27 public Jia(int n1, int n2) 28 : base(n1, n2) 29 { } 30 public override int GetRes() 31 { 32 return base.Num1 + base.Num2; 33 } 34 } 35 class Jian:JiSuan 36 { 37 public Jian(int n1, int n2) 38 : base(n1, n2) 39 { } 40 public override int GetRes() 41 { 42 return base.Num1 - base.Num2; 43 } 44 } 45 class Cheng:JiSuan 46 { 47 public Cheng(int n1, int n2) : base(n1, n2) { } 48 public override int GetRes() 49 { 50 return base.Num1 * base.Num2; 51 } 52 } 53 class Chu:JiSuan 54 { 55 public Chu(int n1, int n2) 56 : base(n1, n2) 57 { } 58 public override int GetRes() 59 { 60 return base.Num1 / base.Num2; 61 } 62 } 63 }
多继承的时候
如果GuangDongRen重写,则调用GuangDongRen的sayhi()方法,如果没有则查看GuangDongRen父类Chinese,如果Chinese重写,则调用Chinese的sayhi()方法,否则调用person的sayhi()方法
为了多态