继承和多态
*继承可以让class具有一种特殊的能力,即实现class本身定义的所有功能外,还可以对父类(或称为基类、超类)的某些属性和功能进行扩展,这样的类我们称之为子类(或派生类)。
继承有如下的几个规则:
1. 可传递性:
如: C是B的子类,B是A的子类,那么C会同时继承B和A;(object为所有类的基类)
2. 唯扩展性:
子类应是对父类的扩展,而不能在子类除去父类里面的定义;
3. 构造函数和析构函数不能被继承:
除去构造函数和析构函数不能被继承,其他的成员都能被继承(注意区别:能被继承和能被访问,是两个概念)
4. 重载屏蔽性:
如果子类定义了和父类成员同名的新成员,那么会执行重载和覆盖逻辑。但要明白的是,这样做,并不是删除了父类的这些成员,而是不能再访问这些被重载和覆盖的成员而已。
5. 子类可以从父类的虚方法、虚属性以及虚索引器进行重载(即多态)
我们可以借用override关键字对父类的虚方法、虚属性以及虚索引器进行重载;
同时,我们也可以借用override关键字对抽象父类的抽象方法进行重载。
abstract和virtural的区别:
(1) abstract可以修饰class以及abstract class内部的函数、属性和索引器;而virtual不可以修饰class;
(2) abstract修饰内部的函数、属性和索引器的时候,必须在abstract class才可以;而且abstract函数、属性和索引器不可以在abstract class里面有实现,但virtual必须要有实现。
(3) virtual既可以修饰abstract class里面的函数、属性和索引器,也可以修饰一般class里面的函数、属性和索引器;
*基础知识扩展:什么是索引器?
索引器允许类或者结构的实例按照与数组相同的方式进行索引取值,索引器与属性类似,不同的是索引器的访问是带参的。
A. 索引器和数组比较:
(1)索引器的索引值(Index)类型不受限制;
(2)索引器允许重载;
(3)索引器不是一个变量;
B. 索引器和属性的不同点
(1)属性以名称来标识,索引器以函数形式标识;
(2)索引器可以被重载,属性不可以;
(3)索引器不能声明为static,属性可以;
下面一个简单的例子可见一斑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
运行结果:
A
B
C
6. 子类只能继承一个父类(class),而可以继承多个接口(interface)(多重继承)
*多态性:同一操作作用于不同的类的实例,将产生不同的执行结果,即不同类的对象收到相同的消息时,得到不同的结果。
下图所示的类之间继承关系和多态用法,可以让大家更好了解这些概念的意义:
具体的实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
程序运行测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
|
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
*多重继承
类和接口都可以继承接口,而且可以继承不止一个接口。
需求:
IDraw接口,定义DrawLine、DrawCircle和DrawRectangle方法;
Drawer,定义为抽象类,实现IDraw接口,附加属性Name;
ImpressionistDrawer(印象画派画家)类,继承Drawer抽象类;
RealismDrawer(写实主义画派画家)类,继承Drawer抽象类。
如此,代码如下:
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
运行结果:
The realism drawer:莫柰 is drawing a circle with pencil.
The realism drawer:莫柰 is drawing a line with pencil.
The realism drawer:莫柰 is drawing a rectangle with pencil.
The impressionist drawer:弗洛伊德 is drawing a circle with pen.
The impressionist drawer:弗洛伊德 is drawing a line with pen.
The impressionist drawer:弗洛伊德 is drawing a rectangle with pen.
扩展一下,比方说:这些画家除了要画画之外,一样都要吃饭睡觉打豆豆,怎么处理呢?
我们当然不能把吃饭睡觉打豆豆归为IDraw这个intercace里面,因为这完全是不相干的行为呀!于是,我们考虑新建一个interface
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|