@property
- 作用:自动生成getter、setter方法的声明
- 因为是生成方法的声明,所以应该写在@interface类的声明之中。
- 语法:
@property 数据类型 名称
- 原理
- 编译器在编译的时候,会根据@property生成getter和setter方法
- 使用@property注意
- @property的类型和属性的类型一致
- @property的名称和属性的名称一致(去掉下划线)
@synthesize
- 作用:自动生成getter、setter方法的实现
- 语法:
@synthesize 名称
- 原理
- 编译器在编译的时候,会根据@synthesize实现getter和setter方法
- 实现的方法:将参数直接赋值给自动生成的那个私有属性(不是自己写的),并且没有任何逻辑验证
- 希望@synthesize不要去自动生成私有属性
//这样就不再自动生成了
@synthesize age = _age;
- 批量生产
@property 类型 名称1,名称2;
@synthesize 名称1=_名称1,...;
- 现在只写@property就可以实现生成和实现了
- 生成时没有做任何逻辑验证
- 所以,我们可以重写setter来自定义验证逻辑,如果重写了setter,还会自动生成getter,重写getter也会自动生成setter
- 如果两个同时重写,那么就不会自动生成了
- 可以继承,但在子类的内部无法直接访问,但可以用getter和setter访问
- 静态类型:指的是一个指针指向的对象是一个本类对象
- 动态类型:指的是一个指针指向的对象不是本类对象
- 编译检查:看指针所属的类型中有没有这个方法
- 运行检查:看这个对象中是否有这个方法
- LSP:任何的指针可以指向任意的对象,编译器不会报错
- 判断指针指向的对象中是否有这个方法可以执行
BOOL b1 = [p1 respondsToSelector:@selector(age)];
if(b1==YES){
[p1 sayHi];
}
- 第二种方法,判断指定的对象是否为指定类的对象或者子类对象
BOOL b1 =[p1 isKindOfClass:[NSObject class]];
NSLog(@"b1=%d",b1);
BOOL b2 = [p1 isMemberOfClass:[Person class]];
NSLog(@"b2=%d",b2);
[Student isSubclassOfClass:[person Class]];
[Person instanceMethodForSelector:@selector(satHi)];
NSObject
- 可以指向任意的OC对象(万能指针,所以OC类的父类)
- 缺点:如果要调用指向的子类对象独有的方法,就必须要做类型转换
id指针
- 万能指针,在定义的时候已经加了*,所以声明时不用加*。
- NSObject和id的异同。
- 相同点:万能指针 都可以执行任意的oc对象。
- 不同点:NSObject指针 会做编译检查,id类型不会做编译检查
- 注意
- id指针不能使用点语法,只能调用方法
- 如果想要使用万能指针id比较方便
- 父类中的类方法创建一个父类对象返回
- 如果返回值写为父类类型的,那么子类来调用这个方法得到的就是父类指针,- - 解决方法:把返回值改为id类型的
- 方法的内部创建对象的时候,不要写死,因为写死创建的对象就固定了。我们希望那一类来调用这个方法就创建那一个类的对象。把类名写为self,那一个类来调用这个方法,self就指的是那一个类。创建的就是那一个类。
+(id)person
{
return [self new]
}
- 方法的返回值是id类型的,问题就是任意指针都可以接收这个方法的返回值。编译器连个警告都没有。如果方法的返回值是instancetype,代表方法的返回值是当前这个类的对象。
+(instancetype)person
{
return [self new]
}
- 使用建议
- 如果方法内部是在创建当前类的对象,不要写死成类名【类名 new】,而是用self代替
- 如果方法的返回值是当前类的对象,也不要写死,而是写instancetype
- id和instancetype的区别
- instancetype只能作为方法的返回值,不能在别的地方使用,id既可以声明指针变量,也可以作为参数,也可以作为返回值。
- instancetape是1个有类型的,代表当前类的对象
- id是一个无类型的指针,仅仅是一个地址,没有类型的指针