标签:
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -----
第一讲 多态的介绍
本小节知识点:
1、【了解】什么是多态?
2、【掌握】多态的条件
3、【了解】多态的优点
提出一个问题:
大家来根据现在学习的知识,思考一个问题:父类能否访问子类方法?
1、什么是多态?
什么是多态:多态就是某一类事物的多种形态
猫: 猫 -->动物
狗: 狗 --> 动物
男人: 男人 --> 人 ---> 高级动物
女人: 女人 --> 人 ---> 高级动物
程序中的多态:不同的对象以自己的方式相应相同名称方法的能力称为多态。
2、多态的条件
多态的条件:有继承关系、有方法重写
父类的生命变量指向子类对象。
//代码体现:用父类类型的指针类型指向了子类对象,这就是多态
狗 *g = [狗 new];
动物 *a = [狗 new];
猫 *c = [猫 new];
动物 *a = [猫 new];
3、多态的优点
多态的主要好处就是简化了编程接口。它容许在类和类之间重用一些习惯性的命名,而不用为每一个新加的函数命名一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类的区分开来。
多态也使得代码可以分散在不同的对象中而不用试图在一个函数中考虑到所有可能的对象。这样使得您的代码扩展性和复用性更好一些。当一个新的情景出现时,您无须对现有的代码进行改动,而只需要增加一个心得类和新的同名方法。
第二讲 多态的概念和条件
本小节知识点:
1、【掌握】如何实现多态
2、【了解】多态的原理
1、如何实现多态
Animal是父类,子类有Cat 和Dog,子分别重写了父类中的eat方法;实例化对象的时候可以用下面的方法:
Animal *ani = nil;
//实例化猫的对象
ani = [Cat new];
[ani eat];
//实例化狗的对象
ani = [Dog new];
[ ani eat];
2、多态的原理
动态绑定:
动态类型能使程序直到执行时才确定对象所属类型。
动态类型绑定能使程序直到执行时才确定要对对象调用的实际方法。
OC不同于传统程序设计语言,它可以在运行时加入新的数据类型和新的程序模
块:动态类型识别,动态绑定,动态加载。
id类型:通用指针类型,弱类型,编译时不进行类型检查。
3、多态的注意点
1)如果存在多态,父类可以访问子类特有的方法。
假设 子类 Dog 有一个特有的方法bark
[dog bark];
Animal *an2 = [Dog new];
[(Dog *)an2 bark]; //把父类的指针,强制类型转换
2)如果不存在多态,父类是不可以访问子类特有的方法的
Animal *an3 = [Animal new];
[(Animal *)an3 bark]; //错误的,不能强制转换
1 #import <Foundation/Foundation.h>
2
3 @interface Animal : NSObject
4 -(void)run;
5 @end
6
7 #import "Animal.h"
8
9 @implementation Animal
10 -(void)run{
11
12 NSLog(@"动物在跑");
13 }
14 @end
15
16 #import "Animal.h"
17
18 @interface Cat : Animal
19
20 @end
21
22 #import "Cat.h"
23
24 @implementation Cat
25 -(void)run{
26
27 NSLog(@"猫在爬树,被蜜蜂蜇了!");
28
29 }
30 @end
31
32 #import "Animal.h"
33
34 @interface Dog : Animal
35 -(void)run; //可以不写
36 -(void)eat;
37 @end
38
39 #import "Dog.h"
40
41 @implementation Dog
42
43 -(void)run{
44
45 NSLog(@"狗以80码的速度冲出去,没撞树上!");
46
47 }
48 -(void)eat{
49 NSLog(@"狗在吃东西");
50 }
51 @end
52
53 #import "Dog.h"
54
55 @interface BigYellowDog : Dog
56
57 @end
58
59 #import "BigYellowDog.h"
60
61 @implementation BigYellowDog
62 -(void)run{
63
64 NSLog(@"大黄狗在跑,撞猪身上了");
65 }
66 @end
67
68 /*
69 多态的概念:
70
71 不同的对象以自己的方式响应父类同名的方法,这就是多态
72
73 体现出来:
74
75 父类的指针指向了子类的对象
76
77 多态的条件:
78
79 1)有继承关系
80 2)有方法重写(子类把父类的同名方法给重写了)
81
82 */
83
84
85 #import <Foundation/Foundation.h>
86 #import "Dog.h"
87 #import "Animal.h"
88 #import "Cat.h"
89 #import "BigYellowDog.h"
90 int main(int argc, const char * argv[])
91 {
92
93 @autoreleasepool {
94 //****没有使用多态*****
95 Animal *ani = [Animal new];
96 [ani run];
97
98 Dog *d1 = [Dog new];
99 [d1 run];
100
101 Cat *cat = [Cat new];
102 [cat run];
103
104 //****** 使用多态 *******
105 //父类指针 指向了子类对象
106 Animal *a2 = [Dog new];
107 [a2 run];
108
109 Animal *a3 = [Cat new];
110 [a3 run];
111
112 Dog *d2 = [BigYellowDog new];
113 [d2 run];
114
115 Animal *ani5 = [BigYellowDog new];
116 [ani5 run];
117
118 //*******多态的使用注意*****
119 Animal *an6 = [Dog new];
120 //an6 Animal类型
121 //编译的时候会报错
122 // [an6 eat]; //报错的
123 //能否执行? [(Dog *)an6 eat]; 把an6强制转换为 Dog类型
124 [(Dog *)an6 eat];
125
126 Animal *a7 = [Animal new];
127 // [a7 eat]; //不可以 ,错误的用法
128 //骗编译器 本身还是Animal对象 ,实际上没有这个方法
129 //Dog 类有eat方法, Animal类没有eat方法的
130 [(Dog *)a7 eat];
131 }
132 return 0;
133 }
第三讲 类的本质
本小节知识点:
1、【了解】类类型的对象
2、【掌握】类的本质
3、【掌握】类对象如何获取
1、类类型的变量(实例变量)
Person *p = [Person new];
//把类的代码加载到代码区
//产生一个类对象,类型是Class isa指向代码区的Person类
//实例化对象三件事
//申请空间 初始化 返回地址
//对象isa 指向类对象
2、类的本质
类的本质其实也是一个对象(类对象)
类对象
类对象在程序运行时一直存在。
类对象是一种数据结构,存储类的基本信息:类大小,类的版本以及消息与函数的映射表等。
类对象所保存的信息在程序编译时确定,在第一次使用该类的时候被加载到内存中。
类对象代表类,class代表类对象,类方法属于类对象。
如果消息的接收者是类名,则类名代表类对象。
运行时,所有类的实例都由类对象生成,类对象会把实例的isa的值修改成自己的地址,每个实例的isa都指向该实例的类对象。
从类对象里可以知道父类信息、可以响应的方法等
类对象只能使用类方法,不能用实例方法。
Person *p = [Person new];
p 实例对象
Person 也是一个对象(类对象),是Class类型
3、类对象如何获取
1)通过实例对象获取
Dog *dog = [Dog new];
Dog *d2 = [Dog new ];
//第一种方法获取类对象
Class c = [dog class];
Class c2 = [d2 class];
2)通过类名获取(类名其实就是类对象)
Class c3 = [Dog class];
第四讲 类对象的使用
本小节知识点:
1、【了解】类对象的用法
1 #import <Foundation/Foundation.h>
3 @interface Person : NSObject
4 -(void)test;
5 +(void)test;
6 @end
8 #import "Person.h"
10 @implementation Person
11
12 -(void)test{
13 NSLog(@"-test");
15 }
16 +(void)test{
18 NSLog(@"+test");
19 }
20
21 @end
22
23 /*
24 原来使用类名可以做哪些事情?
25 创建对象
26 [Person new];
27
28 调用类方法
29 [Person test]; //test 是类方法
30
31 Person *p = [Person new ];
32 Class c1 = [p class]; //Person
33
34 c1---->Person
35
36 类对象的使用:
37 1)创建实例对象
38 Person *p1 = [c1 new];
39 2)调用类方法
40 [c1 test];
41
42 */
43 #import <Foundation/Foundation.h>
44 #import "Person.h"
45 int main(int argc, const char * argv[])
46 {
48 @autoreleasepool {
49 //获取类对象
50 Class c1 = [Person class];
51 //c1 ----> Person
52 //使用类对象创建实例对象
53 Person *p = [c1 new];
54 [p test]; //-test 表示对象创建成功,c1当Person来用的
55 //使用类对象调用类方法
56 [c1 test]; //+test
59 }
60 return 0;
61 }
第五讲 类对象的存储细节
【了解】类对象的存储
1、类对象的存储
第六讲 SEL类型
【了解】SEL类型
1、SEL类型
SEL:全称selector表示方法的存储位置。
方法在内容中是怎么存储的?
Person *p = [[Person alloc] init];
[p test];
寻找方法的过程:
(1)首先把test这个方法名包装成sel类型的数据:
(2)根据SEL数据找到对应的方法地址:
(3)根据方法地址调用相应的方法。
(4)注意:在这个操作过程中有缓存,第一次找的时候是一个一个的找,非常耗性能,之后再用到的时候就直接使用。
关于 _cmd:每个方法的内部都有一个_cmd, 代表着当前方法.
注意:SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去寻找对应的方法地址,找到方法地址后就可以调用方法。这些都是运行时特性,发消息就是发送SEL,然后根据SEL找到地址,调用方法。
SEL s1 = @selector(eat);
//通过s1 去调用了
[p2 performSelector:s1];
1 #import <Foundation/Foundation.h>
2
3 @interface Person : NSObject
4 -(void)test;
5 @end
6
7 #import "Person.h"
8
9 @implementation Person
10 -(void)test{
11 NSLog(@"-test");
12 }
13 @end
14
15 #import <Foundation/Foundation.h>
16 #import "Person.h"
17 int main(int argc, const char * argv[])
18 {
19
20 @autoreleasepool {
21
22 Person *p = [Person new];
23 [p test]; //跟下面SEL一样
24
25 //手动的把test方法包装成 SEL 类型
26 SEL s1 = @selector(test);
27 //响应方法
28 [p performSelector:s1];
29 }
30 return 0;
31 }
标签:
原文地址:http://www.cnblogs.com/xiaokang520/p/5062344.html