1、点语法
Xcode 自动把点语法展开为set方法和get方法,所以一定要有set和get方法。
Person *p = [[Person alloc] init];
[p setAge:18];
//点语法:Xcode的特性,Xcode帮我们做代码替换
//对象.属性名
//注意,此时(p.age)并不是直接访问实例变量
//而是Xcode看到点语法后,会自动替换
//p.age = 18;--替换-->[p setAge:18];
p.age = 20;
NSLog(@"%d",[p age]);
//注意,此处p.age是出现在等号的右侧
//实际上,当Xcode看到p.age出现在等号的右侧后
//会自动替换p.age---->[p age];
int a = p.age;
NSLog(@"%d",a);
//强调:p.age到底是替换成get方法还是set方法,一般取决于它出现在等号左侧还是右侧(是设置值,还是取值)
2、@property用法
@property int age;
相当于在.h文件set和get方法的声明
格式
@property 数据类型 方法名(去掉set)
作用:
1、Xcode4.4之前,用于帮助我们实现get/set方法的声明
2、Xcode4.4之后,有增强功能,可以只使用@property 而不需要使用@synthesize,声明和实现了_age的get和set方法,
操作的是带有下划线的实例变量,如果当前类没有下划线的实例变量,系统会帮我们自动生成。
所以,@property int age;//生成一个int _age的实例变量(该变量是私有的,不能被子类继承),声明和实现_age的get和set方法。
注意事项:
@property只能写在@interface @end中;
@interface Person : NSObject
{
int _age;
}
@property int age;
//相当于
//-(void)setAge:(int)age;
//-(void)age;
@end
3、@synthesize用法
@synthesize是在m文件里get/set方法的实现
@property int age;在.h文件set和get方法的声明
@synthesize age;
指定实例变量赋值
@property int a;
@synthesize a = _b; //表示用a的get和set方法,修改属性b的值
4、动态类型&静态类型
多态:允许不同的类定义相同的方法(父类Animal的指针可以指向子类Dog,可以调用子类的同名方法: Animal *ani = [Dog new];)
动态类型:程序直到执行时才能确定所属的类。(典型的是多态)
静态类型:编译时就确定类
5、为什么要有动态类型?
多态的出现时为了代理模式
6、id类型
id是一种通用的对象类型,可以存储任何类型的对象指针,万能指针
NSObject和id的区别
Animal *ani = [Animal new];
[ani run];//动物在跑
Animal *ani2 = [Dog new];//多态
[ani2 run];//狗在跑
//NSObject访问子类特有的方法run,需要强制转换
NSObject *ani3 = [Animal new];
[(Animal *)ani3 run];
//访问子类特有的方法
ani3 = [Dog new];
[(Dog *)ani3 run];
//NSObject是所有类的基类,可以指向任何子类
//注意id的使用,编译时不检查id,允许时才确定,动态类型
id obj;
obj = ani2;
[obj run];
obj = ani;
[obj run];
//NSObject和id都可以指向任何对象
//NSObjct对象会进行编译时检查(需要强制类型转换)
//id不需要强制类型转换,id可以直接用
//编译器看到id以后,认为是动态类型,不在检查类型。
7、动态绑定
在OC中,一个对象内是否调用指针的方法不是由编译器决定而是由运行时决定,这称为方法的动态绑定
8、动态类型检测方法
判断类型
-(BOOL) isKindOfClass :classObj 判断实例对象是否是这个类对象或这个类的子类对象(对象和类之间的关系)。
类的本质就是一个类对象[类名 class]。
Animal *ani = [Animal new];
//1)判断某个对象是否是类的实例对象,或者子类的实例对象
//isKindOfClass使用格式:[对象 isKindOfClass 类对象]:
BOOL a = [ani isKindOfClass:[Animal class]];
NSLog(@"%d",a);//1
-(BOOL)isMemberOfClass:classObj 判断实例对象是否是指定的类对象(对象和类之间的关系)。
+(BOOL)isSubclassOfClass:classObj 判断类是否是指定类的子类(类和类之间的关系)。格式:[类A isSubclassOfClass:类B ]
判断对象能否响应指定的方法
-(BOOL) respondsToSelector: selector 判断实例是否有这样方法
@selector(run)返回的是SEL类型,表示方法run的存储位置
BOOL b = [ani respondsToSelector:@selector(run)];
NSLog(@"%d",b);//1
+(BOOL) instancesRespondToSelector:selector 判断类是否有这个方法,此方法是类方法。
BOOL b = [Animal respondsToSelector:@selector(run)];
NSLog(@"%d",b);//1
9、响应方法
-(id) performSelector:selector (应用selector指定的方法),响应无参的方法
<span style="white-space:pre"> </span>Animal *ani = [Animal new];
[ani performSelector:@selector(run)];//响应方法run
-(id) performSelector:selector withObject:object 传递参数,响应有一个参数的方法
-(id) performSelector:selector withObject1:object1 withObject2:object2 传递参数,响应有两个个参数的方法
还有delay延时的功能。
10、构造方法
用来初识化对象的方法,是个对象方法。
1)重写init方法
重写构造方法的目的,是为了让对象创建出来,成员变量就会有一些固定的值。
[Person alloc]的时候,内存已经被清0,这个刚刚分配的对象并不能立即使用,需要先初始化该对象,若没有进行初始化,可能出现一些不可预测的错误。
[[Person alloc] init]初始化,返回地址。
当子类把父类的init覆盖了,默认先执行子类的
-(instancetype)init{
//先让父类把父类原来做的事情做完
//先利用父类的init方法为子类实例的父类部分属性初始化
//为了防止父类的初识化方法release掉了self指向的空间并重新alloc了一块空间,这时的话,[super init]可能alloc失败,这时就不再执行if中的语句
self = [super init];
//判断父类是否初始化成功
if(self){
//此处写子类初识化的内容
_age = 10;
}
return self;
}
2)自定义构造方法
是一个对象方法,返回值是id类型(instancetype),方法名一定要以 initWithXXXX
[[Person alloc] initWithXXXX:10];//把init改为自定义的构造方法,此处有一个参数给10