分类有什么好处呢?
分类可以实现团队开发的便利性,也就是说一个类可以有多个人来实现。另外,分类也可以用来对系统自带的类进行扩充。
那么使用分类有哪些注意点呢?
1、 Category可以访问原始类的实例变量,但不能添加变量,只能添加方法。如果想添加变量,可以考虑通过继承创建子类。
2、Category可以实现原始类的方法,但不推荐这么做,因为它是直接替换掉原来的方法,这么做的后果是再也不能访问原来的方法。
3、多个Category中如果实现了相同的方法,只有最后一个参与编译的才会有效。
4、类中方法调用的优先级是:分类(最后编译的分类优先级最高)> 原来类 > 父类。
为什么类方法不能使用实例变量?
类方法的使用没有创建对象,在堆区中就没有为实例变量分配存储空间,实例变量就没有值,访问就没有意义。
匿名类:
使用匿名类访问成员变量(能,只能访问一次),以后再次访问实际上访问的是新空间.
Set的优势:1)不让数据暴露在外面,保证了数据的安全性。2)对设置的数据进行过滤。
OC中static关键字的使用:
1)可以使局部变量延长生命周期
2)变为静态变量,位于程序的全局数据区
3)若作为全局变量,可将声明放到实现文件的开始部分
self在类方法中使用,指代的是当前类
【对象名 class】返回的是当前类(地址)
NSLog(@“Person =%p”,[p class]);
用在对象方法中
指代的是调用当前方法的对象
就是说当一个对象调用对象方法的时候,在被调用的对象方法内,用self指代自己,可以再次调用其他对象方法(能够达到着这种效果的方法,还有一种,那就是将本对象作为参数传递到自己调用的方法中)
self存储的是堆区对象的首地址,和对象名存储的地址一样(self可能存放在内存堆区)
多态
用一个基类的指针指向子类的对象,在函数调用时可以调到正确版本的函数。
1、用一个基类的指针指向一个子类对象
2、用一个基类的指针当函数的形参,用这个指针可以接受到任何它的子类对象也包括他自己。
3、在复合类中,尽量引用高层次的类(基类的指针)当做类的成员变量,这样就可以通过它创建出他所对应的任何子类对象包括它自己。
self和super:self是指当前的对象的指针,super是指向父类的指针。
MRC下,程序中(alloc,copy, retain)必须要和release成对出现。
当使用初始化方法初始化一个对象时,有三处可能导致程序错误:1、方法的参数。2、执行父类的init方法。3、类中特有实例变量的初始化。
野指针:定义的指针变量没有初始化,或者说,指向的空间已经被释放
内存泄漏:指针没了,空间还在。
Person *p = [[Person alloc] init]; p存在栈区,[[Person alloc] init]堆区。
如果栈区的p已经释放了,而栈区的空间还没有释放,堆区的空间就被泄漏了。
nil:如果一个【对象】没有被赋值,默认的是nil
Nil:给【类对象赋值】 NULL:通用指针,空指针。
【NSNul null】:是一个对象,他用在不能使用nil的场合
【nil run】 没有任何效果,但是也不会报错。
d = nil;可以给对象赋值 Nil可以给类赋值
多个对象的野指针问题:
当有多个对象需要release的时候,比如:人用车,在重写人release的时候,在其中先release车,这个,不会造成人被释放,无法找到相应的车,造成车的内存泄漏。
对于对象作为另一个类的实例变量
人有一条狗
Dog *_dog;
-(void)setDog:(Dog *)dog
{
if (_dog != dog) //判断对象是否是原对象
[_dog release]; //release旧值
_dog = [dog retain]; //retain新值并且赋值给实例变量
}
继承:在子类中大大减少代码的缩写量,十分方便维护程序。
我们在OC中定义一个类的时候,它的成员变量默认情况下是@protected的。这是因为我们的成员变量一般不允许直接去访问,如果需要修改和访问成员变量我们就要用到成员变量的set方法和get方法。
平常写代码的时候要注意在set方法里写上对传入的数据的判断,以避免传入的数据不合理。
当省略成员变量的时候,@synthesize可以省略,@synthesize会自动在方法的实现中对成员变量进行定义,而且定义的成员变量是@private类型的。当省略@synthesize时我们的@property又会自动生成@synthesize代码,所以我们可以只写@property就可以实现定义变量、声明set和get方法和实现set和get方法。
- 为什么使用set和get方法?
这是因为我们的成员变量要进行封装,不能让外部直接对变量进行修改和访问。这提高了安全性的同时也可以让我们不需要去关注实现的细节。
- 总结:
1、set方法和get方法是用来对数据进行设置和取值的。
2、在set方法中我们可以对传入的数据进行判断,以防止输入一些不合理的值。
3、我们可以利用@property来实现set和get方法的声明,利用@synthesize对set和get方法进行实现。这样可以简化我们要输入的代码。
4、定义属性的时候最好在前面加上下划线。
- (原子性)atomic: 设置成员变量@property属性时,默认为atomic,提供多线程安全。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic, setter函数会变成下面这样:
1 {lock} 2 if (property != newValue) 3 { 4 [property release]; 5 property = [newValue retain]; 6 } 7 {unlock}
- nonatomic: 禁止多线程,变量保护,提高性能。
- atomic 是 OC 使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。
- 类的关系可以总结为两种:组合和继承。
- 组合为Has-A关系,继承为Is-A关系,如果类之间存在Has-A关系,则在程序中可以使用组合表示。如果类之间存在Is-A关系或者要实现代码复用,则在程序中可以使用继承实现。
- autorelease:缺点:拉长了对象的内存的生命周期,让对象活的更久,消耗内存。优点:不用管理内存,自动发送release消息。
- 使用autorelease需要注意:
- 首先,发送过多的autorelease消息,就和你发送太多的release一样,当清空自动释放池时,可能会引发内存故障。
- 其次,虽然release消息可以被替换为autorelease,但出于系统性能的考虑,可以使用release的地方尽量不使用autorelease,因为自动释放池所做的工作要比直接使用release多很多。
- 最后,自动释放池的“延迟释放机制”可能会导致无用的内存消耗。