一.多态
1. 多态概念,定义
什么是多态:多态就是某一类事物的多种形态;
//程序中的多态:不同的对象以自己的方式响应相同名称方法的能力称为多态
表现形式: Animal *ani = [Dog new];
多态条件:1.有继承关系 2.有方法的重写
2.多态代码实现:
//实例化猫的对象
Animal *animal = [Cat new]; //父类的指针指向子类对象;
[animal eat];
//实例化狗的对象
animal = [Dog new]; //父类的指针指向子类对象。
[animal eat];
//多态的优点:
多态的主要好处就是简化了编程接口。它容许在类和类之间重用一些习惯性的命名,而不用 为每一个新加的函数命名一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类的区分开来。
多态也使得代码可以分散在不同的对象中而不用试图在一个函数中考虑到所有可能的对象。 这样使得您的代码扩展性和复用性更好一些。当一个新的情景出现时,您无须对现有的代码进行改动,而只需要增加一个新的类和新的同名方法。
3.多态注意点:
1) 如果存在多态,父类是可以访问子类特有的方法
假设子类Dog 有一个特有的方法bark
Animal *an2 = [Dog new]; //编译时看等号左边,运行时看等号右边
[(Dog*)an2 bark]; //把父类的指针,强制类型转换
2) 如果不存在多态,父类是不可以访问子类特有的方法的
Animal *an3 = [Animal new];
[(Dog*)an3 bark]; //错误的,不能强制转换,这只是欺骗了编译器,但是程序运行的时候会崩溃
二.类对象
1,类的本质其实也是一个对象(类对象);
类对象
*类对象在程序运行时一直存在。
*类对象是一种数据结构,存储类的基本信息:类大小,类名称,类的版本以及消息与函数的映射表等
*运行时,所有类的实例都由类对象生成,类对象会把实例的isa的值修改成自己的地址
*每一个对象都包含一个指向其类对象的isa指针。
2、类对象如何获取
//通过实例对象获取
Dog *d1 = [Dog new];
Dog *d2 = [Dog new];
Class c = [d1 class];
Class c2 = [d2 class];
//通过类名获取(类名其实就是类对象)
Class c3 = [ Dog class ];
因为类对象在整个程序中只存在一份,
所以 c = c2 = c3
3.类对象的使用
1)可以用来调用类方法 :
//获取类对象
Class c1 = [Person class];
//使用类对象调用类方法
[c1 test]; // test是一个+号方法
2)可以用来实例化实例对象, 并且调用对象方法
//获取类对象
Class c1 = [Person class];
//使用类对象创建实例对象
Person *p = [c1 new];
[p test]; // -test 调用对象方法
4.SEL类型
SEL:全称selector。 表示方法的存储位置。
SEL是一种新的数据类型。和id、class一样。
Person *p = [Person new];
SEL s1 = @selector(test);
[p performSelector:s1];
寻找方法的过程:
(1)首先把test这个方法名包装成sel类型的数据;
(2)根据SEL数据找到对应的方法地址;
(3)根据方法地址调用相应的方法。
(4)注意:在这个操作过程中有缓存,第一次找的时候是一个一个的找,非常耗性能,之后再用到的时候 就直接使用。
注意:SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去寻找对应的方法地址,找到方法地址后就可以调用方法。这些都是运行时特性,发消息就是发送SEL,然后根据SEL找到地址,调用方法。
三.点语法
1. 传统setter, getter方法
-(void)setAge:(int)age{
_age = age;
}
-(int)age{
return _age;
}
2. 点语法
本质上展开之后相当于调用setter, getter方法
p.age = 10; 展开之后等价于 [p setAge:10]; // setter方法
NSString *name = p.age; 等价于NSString *name = [p name]; // getter方法
对象. 成员变量 //展开之后到底是setter方法, 还是getter方法, 看在等号的左边还是右边,
如果是等号左边就是setter方法, 在等号右边是getter方法
3. 点语法陷阱 :
在set方法使用self.
- (void)setAge:(int)newAge {
self.age = newAge;
}
会造成死循环
4、点语法注意
点语法的本质是方法的调用,而不是访问成员变量,当使用点语法时,编译器会自动展开成相应的方法。
切记点语法的本质是转换成相应的set和get方法,如果没有set和get方法,则不能使用点语法。//*************
四.@property&@synthesize
@property的语法:
使用:
@property int age;
@property特性:
1,@property只能写在@interface .......@end中。
2,@property 用来自动生成成员变量age的get/set方法声明(xcode4.4以前) 。
3,xcode4.4以后property做了增强 不但帮助我们自动生成get/set方法的声明还帮助我们自动生成get/set方法的实现.并且生成了带下划线的成员变量
@synthesize用法:
1. @synthesize age; 表示成员变量age的get和set方法的实现
2. @synthesize 给指定的实例变量赋值。
@synthesize age = _age;// 指定下划线成员变量(int _age;)
注意;
如果是@synthesize的话,变量名要先在.h文件中声明。
@property,@synthesize在xcode4.4之前,这两个可以配合使用,用于简化set和get方法的定义和实现。
重写setter, getter方法:
只能重写setter, 或者getter方法中的一个
如果重写两个会报错.
动态类型&静态类型
多态:允许不同的类定义相同的方法。
动态类型:程序直到执行时才能确定所属的类。
静态类型:将一个变量定义为特定类的对象时,使用的是静态形态。
//为什么要有动态类型?
多态的出现时为了让不同的类能使用同名的方法。这会让程序的可读性大大提高,也降低了编程难度。
//编译时和运行时检查
因为存储在id变量中的对象类型在编译的时候是无法确定的,所以一些事情是需要在运行时才能够确定。
五.id类型(万能指针)//********
id 是一种通用的对象类型,它可以用来存储属于任何类的对象 也可以理解为万能指针
id和NSObject区别:
id不会进行编译检查, NSObject会进行编译检查 //!!!!!!!!?
id和instancetype类型区别:
1. id和instancetype都可以用来作为方法的返回值
2. id可以用来定义类型,instancetype不能用来定义类型
id obj;
instancetype obj2; // 错误
3. instancetype可以精确确定返回值类型, id不能精确返回值类型
六.动态类型
1. 动态类型:
运行的时候确定的类型
2. 动态绑定:
动态绑定是基于动态类型的:
基于动态类型,在某个实例对象被确定后,其类型便被确定了。该对象对应的属性和响应的消息也被完全确定,这就是动态绑定。
动态绑定所做的,即是在实例所属类确定后,将某些属性和相应的方法绑定到实例上。
//-----------------------
1)在objective-c中,一个对象内能否调用指定的方法不是由编译器决定而是由运行时决定,这被称作是方法的动态绑定。
2)在objective-c里,对象不调用方法,而是接收消息,消息 表达式为: [reciver message];运行 时系统首先确定接收者的类型(动态类型识别),然后根据消息名在类的方法列表里选择相依的方法 执行,所以在源代码里消息也称为选择器(selector)
3)消息函数的作用:
– 首先通过第一个参数的receiver,找到它的isa 指针,然 后在isa 指向的Class 对象中使用第 二个参数selector 查s找方法;
– 如果没有找到,就使用当前Class 对象中的新的isa 指针 到上一级的父类的Class 对象中查 找;
– 当找到方法后,再依据receiver 的中的self 指针找到当前 的对象,调用当前对象的具体实现 的方法(IMP),然后传 递参数,调用实现方法。
– 假如一直找到NSObject 的Class 对象,也没有找到你调 用的方法,就会报告不能识别发送消息 的错误。
//------------------------
3. 动态加载:
动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等;
4. 内省(Introspection)是面向对象语言和环境的一个强大特性,Objective-C和Cocoa在这个方面尤其的丰富。
//**************************************
对象在运行时获取其类型的能力称为内省。//!!!!!!!!!!!!!!
内省是对象揭示自己作为一个运行时对象的详细信息的一种能力。这些详细信息包括对象在继承树上的位置,对象是否遵循特定的协议,以及是否可以响应特定的消息。
// 判断类型
1、-(BOOL) isKindOfClass: classObj
判断实例对象是否是这个类或者这个类的子类的实例。
2、-(BOOL) isMemberOfClass: classObj
判断实例对象是否是这个类的实例。(不管它是否是这个类的子类的实例。)
3、+(BOOL) isSubclassOfClass:classObj
判断类是否是指定类的子类。
//判断对象能否相应指定的方法
4、-(BOOL) respondsToSelector: selector
确定对象是否可以对某个SEL做出响应.
如 SEL s1 = @selector(run);
[dog respondsToSelector:s1];
5、+(BOOL) instancesRespondToSelector: selector
判断类的实例对象是否有这个方法。(此方法是类方法)
6、conformsToProtocol:protocol
检查对象是否符合协议,是否实现了协议中所有的必选方法。@required