10.1派生类的对象和基类的关系
(1)is A 关系(属于关系):
对象是属于类的,因此对象和类是属于关系;子类是属于父类的,因此子类和父类是属于关系;
因为:对象属于类,所以子类对象属于子类;
又因为:子类属于父类,所以子类对象属于父类
10.2 多态的概念
(1)引用符与对象
对象:对象是实存放对象实体的,是存储在堆中;
引用符:引用符中存放的是对象在堆中的地址,是存放在栈中;
有前面理论:子类对象属于父类,所以父类引用符可以指向子类对象;
也即是说:
(a)子类实例(引用,对象)可以赋值给父类引用符(自动化转型)
(b)但是此父类引用符无法调用子类特有的成员,只能调用子类从父类继 承来的成员;
10.3 多态性的运用
1.多态使用
(1)父类定义一个抽象函数,多个子类分别重写这个抽象函数;
(2)设计通用部分(使用父类类型来定义一个形参
(3)产生多个子类,将对象传递给通用部分,调用同样方法,得到不同的结果
abstract class vertebrata //(1)父类定义一个抽象函数,多个子类分别重写这个抽象函数; { abstract public void Show(); } class mammal : vertebrata { public override void Show() { } } class dog : mammal //(2)多个子类分别重写这个抽象函数; { public override void Show() { Console.WriteLine("dog"); } } class peg : mammal { public override void Show() { Console.WriteLine("peg"); } } class brid : mammal { public override void Show() { Console.WriteLine("brid"); } } class Program { static void Main(string[] args) { vertebrata[] animals = { new dog(), new peg(), new brid() }; foreach (vertebrata v in animals) //设计通用部分(使用父类类型来定义一个形参.产生多个子类,将子类对象传递给通用部分; { v.Show(); } Console.ReadKey(); } }
2.除了使用bastract方法和override可以实现多态,也可以用virtual 与overrride实现
但是注意:
(1)由于虚函数(不是抽象函数)必须有方法体,因此设计成空实现或者随便实现;
(2)必须是用overtide重写虚函数(可以不加overtide重写虚函数的哦,但是结果不一样)的中方法,否则父类引用符好像会隐藏子类中同名方法,得不到子类同意同一方法不同的实现;
由于必须要使用override 重写父类中同名方法才能实现多态,因此父类中的同名方法必须修饰为virtual或者basetract;(不修饰为virtual或者basetract就不能使override重写,否则语法错误);
class vertebrata { public virtual void Show() { Console.WriteLine("vertebrata"); } } class mammal : vertebrata { public override void Show() {} } class dog : mammal { public override void Show() { Console.WriteLine("dog"); } } class peg : mammal { public override void Show() { Console.WriteLine("peg"); } } class brid : mammal { public override void Show() { Console.WriteLine("brid"); } } class Program { static void Main(string[] args) { vertebrata[] animals = { new dog(), new peg(), new brid() }; foreach (vertebrata v in animals) { v.Show(); } // ((dog)animals[0]).Show(); //((peg)animals[1]).Show(); Console.ReadKey(); } }
3.将子类实例赋值给基类引用符(自动发生向上转型),父类引用符无法使用子类特有成员;(后者说子类特有成员对父类不可见);
(如果不用override重写,父类引用就会隐藏子类同名方法改写;也即是子类覆盖的父类方法,父类不可见(说白了这个覆盖的方法也算是子类特有的,由于子类特有成员对父类都是不可见的)
class vertebrata { public void Show() { Console.WriteLine("vertebrata"); } } class mammal : vertebrata { public void Show() { } } class dog : mammal { public void Show() { Console.WriteLine("dog"); } } class peg : mammal { public void Show() { Console.WriteLine("peg"); } } class brid : mammal { public void Show() { Console.WriteLine("brid"); } } class Program { static void Main(string[] args) { vertebrata[] animals = { new dog(), new peg(), new brid() }; foreach (vertebrata v in animals) { v.Show(); //如果不用override重写,父类引用就会隐藏子类同名方法改写;也即是子类覆盖的父类方法, //父类不可见(说白了这个覆盖的方法也算是子类特有的,由于子类特有成员对父类都是不可见的) } // ((dog)animals[0]).Show(); //((peg)animals[1]).Show(); Console.ReadKey(); } }
10.4 Is运算符
1.is运算符用与判断每个实例是否属于某个类,如果这个实例属于这个类,或者这个类的父类,则返回true,否则返回false;
2.使用方法: 对象 is 类名
class Program { static void Main(string[] args) { int i = new int(); i = 5; Console.WriteLine(i is int); Console.WriteLine(i is object); Console.WriteLine(i is Double); Console.WriteLine(new int() is Double); Console.ReadKey(); } }
10.5 对象转型
(1)由低层次转为高层次称之为向上转型,向上转型是自动进行的,
派生类转为基类是是向上转型,是自动进行的,但是基类不能引用符不能使用子类对象特有的成员;
class A { } class B : A { void show() { Console.WriteLine("show"); } } class Program { static void Main(string[] args) { A aa = new B(); aa.show();//error,父类引用符,无法使用子类特有成员 } }
(2)由高层次转为低层次称之为向上转型,必须要强制转换;
注意:只有引用本身原来就是子类型才能转为子类,如果引用本身原来是父类型或者其他类型,则无法转换
class A { } class B : A { public void show() { Console.WriteLine("show"); } } class Program { static void Main(string[] args) { A aa = new B(); ((B)aa).show(); //强制向下转换:由于aa本来就是子类的实例,所以才能转为子类; A aaa = new A(); //error 由于aa本来就是父类型/或者其他类型,所以就无法转换 ((B)aaa).show(); } }
10.6 接口
待续。。。。
10.7 类关系视图