打个比方:
一个person类中有一个属性age,那么如果用property声明后,set跟get方法仅仅只是做一个_age = age.但是你想想如果你在person类中new一个对象p,那么我可不可以写成 p setAge = -10 ?
一个人的年龄肯定不会有-10岁,如果重写set方法你就可以在set方法中写成
if(age <= 0){
age = 1;
}
也就是说当你给age赋值小于或等于0的时候,age会自动变成1,一个人的年龄是1岁,也比-10岁来的合理.
另一种场合:
子类重写父类中的方法:
在子类中实现与父类中同名的方法,称之为方法重写;
重写以后当给子类发送这个消息的时候,执行的是在子类中重写的那个方法,而不是父类中的方法。
如果想在子类中调用被子类重写的父类的方法,可以通过super关键字
使用场景:当从父类继承的某个方法不适合子类,可以在子类中重写父类的这个方法。
关于重写init方法:
重写init方法时,必须要在init方法中调用父类的init方法即:[super init],且[super init]必须要用self来接收它的返回值,否则报错。
super调用的init方法必须要接收,用self接收。
可以这么理解:我们使用到的Person对象需要通过init返回,而Person中的self指针没有被初始化,所以不知道self指向的是谁,所以需要将[super init]返回的对象内存空间赋给self指针,这样self指针就明确指向了当前的内存空间,所以Person的init方法返回了Person的对象,同时初始化了self指针,当我们使用self指针时,就知道self指向的是哪块内存空间了。
懒加载:
理念:变量不到需要使用的最后一刻,就不要分配空间。什么时候用到变量了,什么再分配
实现措施:重写该属性的getter方法,在getter方法中做判断,当没有分配空间时,先分配再返回,如果已经有空间了,那么就直接返回
懒加载的优点:
1.不需将对象的实例化写到viewDidLoad,可以简化代码,增强代码的可读性
2.对象的实例化在getter方法中,各司其职,降低耦合性
3.对系统的内存占用率会减小
没用懒加载的时候,从plist获取数据,返回一个数组,需要写在viewDidLoad方法中获取
@interface ViewController ()
@property (nonatomic, strong) NSArray *students;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_students = [NSArray arrayWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"students" ofType:@"plist"]];
}
@end
显而易见,当控制器被加载完成后就会加载当前的students,假如students是在某些事件被触发的时候才会被调用,没必要在控制器加载完就去获取plist文件,如果事件不被触发,代表着students永远不会被用到,这样在viewDidLoad中加载students就会十分多余,并且耗用内存.
懒加载代码示例:
- (void)viewDidLoad {
[super viewDidLoad];
}
- (NSArray *)students
{
if (!_students) {
_students = [NSArray arrayWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"students" ofType:@"plist"]];
}
return _students;
}
@end
当需要用到students的时候,就会调用[self students]的方法(即getter方法),此时系统会去调用getter方法,然后再getter方法中获取plist文件内容,然后返回使用
需要注意在getter方法里切勿使用self.students,因为self.students会调用getter方法,造成死循环
_students是直接值访问,而self.students是属性访问,就是通过get/set方法来读取这个值,xcode会默认将两个值通过syncthesize关键字进行同步
举个例子:
- (UIButton *)cover这个方法就是self.cover的get方法,也就是说每次你调用self.cover的时候都会进入这个方法,那么问题来了
如果你在这个方法里用了下面这个语句
if (self.cover == nil );逻辑上就行不通,因为你在这里调用self.cover他会再一次进入这个方法,理论上就会死循环
而_cover是直接值访问的,他不会调用get/set方法,所以就不会有这个问题.
至于后面绿色的地方为什么可以就很好理解了,虽然它也会进入get方法,但是他已经不等于nil了.会直接返回他本身,所以没有问题.