一. 成员变量
(一)变量的作用域主要分为四种:
(1)@public (公开的)在有对象的前提下,任何地方都可以直接访问。
(2)@protected (受保护的)只能在当前类和子类的对象方法中访问
(3)@private (私有的)只能在当前类的对象方法中才能直接访问
(4)@package (框架级别的)作用域介于私有和公开之间,只要处于同一个框架中就可以直接通过变量名访问
2.注意:
无论父类是在@interface还是@implementation声明的成员变量子类都能拥有;但是子类能不能直接通过变量名来访问父类中定义的成员变量是需要看父类中定义的成员变量是由什么修饰符来修饰的。
3.默认:
在.m中成员变量的修饰符为@private.
在.h中成员变量的修饰符@protected.
创建一个学生类,然后分别在.h跟.m中声明4中不同的类型的变量,创建一个MidStudent来继承Student
我们在MidStudent中来调用下看看这些变量哪些可以访问哪些不可以:
有图可以看出,我们在.m里面声明的变量子类是无法访问的(即使给他@public),也会被认为是@private,所以我们的对外属性都会放到.h去声明,然而由于six变量是@private,所以子类还是无法访问的
我们再去外部去调用下MidStudent 对象 看看是什么效果
由于我们没有在Student或他的子类里面,所以只能访问.h中@public修饰的变量,也就是name,由于age是@protrcted在外部是不能被访问的!
二. 属性
点语法:的本质是方法的调用,而不是访问成员变量,当使用点语法时,编译器会自动展开成相应的方法。切记点语法的本质是转换成相应的set和get方法,如果没有set和get方法,则不能使用点语法。
关于@synthesize object = _object 的解释
1、@property的作用是定义属性,声明getter,setter方法。(注意:属性不是变量);
2、@synthesize的作用是实现属性的,如getter,setter方法;
3、总结:一定要分清属性和变量的区别,不能混淆。@synthesize 声明的属性=变量。意思是,将属性的setter,getter方法,作用于这个变量;
4、但Xocde4.5以后,编译器会为你自动实现setter及getter方法,如果他找不到_father,会为你自动创建一个_father的变量;
声明属性的时候会有一些关键词这里简单说下他们的含义:
atomic: 原子性
在objective-c 属性设置里面 默认的就是atomic ,意思就是 setter /getter函数是一个原子操作,如果多线程同时调用setter时,不会出现某一个线程执行完setter所有语句之前,另一个线程就开始执行setter,相当于 函数头尾加了锁 . 这样的话 并发访问性能会比较低 .
nonatomic: 非原子性
非原子操作 一般不需要多线程支持的时候就用它,这样在 并发访问的时候效率会比较高 . 在objective-c里面通常对象类型都应该声明为非原子性的. iOS中程序启动的时候系统只会自动生成一个单一的主线程.程序在执行的时候一般情况下是在同一个线程里面对一个属性进行操作.
getter=getterName
指定 get 方法,并需要实现这个方法 。必须返回与声明类型相同的变量,没有参数.相当于重新命名getter方法
setter=setterName:
指定 set 方法,并需要实现这个方法 。带一个与声明类型相同的参数,没有返回值(返回空值)
readwirte
如果没有声明成 readonly ,那就 默认是 readwrite 。可以用来赋值,执行set方法
readonly
不可以被赋值
assign ( ARC/MRC )
1、这个修饰词是直接赋值的意思 , 整型/浮点型等数据类型都用这个词修饰 .
2、如果没有使用 weak strong retain copy 修饰 , 那么默认就是使用 assign 了. ( 它们之间是有你没我的关系 )
3、当然其实对象也可以用 assign 修饰 , 只是对象的计数器不会+1 . ( 与 strong 的区别 )
4、如果用来修饰对象属性 , 那么当对象被销毁后指针是不会指向 nil 的 . 所以会出现野指针错误 . ( 与weak的区别 )
通常用于标量(简单变量 int , float , CGRect 等)
一种典型情况是用在对对象没有所有权的时候,通常是 delegate ,避免造成死循环(如果用 retain 的话会死循环)
strong ( ARC )
1.直接赋值并且计数器 +1 .
2.在 ARC 里替代了 retain 的作用 .
释放旧对象,将旧对象的值赋予输入对象 ,再提高输入对象的索引计数为 1 ,常使用在继承自 NSObject 的类。(MRC为retain)
retain ( MRC )
1.release 旧对象( 旧对象计数器 -1 ) , retain 新对象( 新对象计数器 +1 ) , 然后指向新对象 .
2.在set方法里面是这样的 :
if (_dog) {
[_dog release];
}
_dog = [dog retain];
weak ( ARC )
-
1.弱指针是针对对象的修饰词 , 就是说它不能修饰基本数据类型 .
2.weak 修饰的对象计数器不会+1 , 也就是直接赋值 .
3.弱引用是为打破循环引用而生的 .
4.它最被人所喜欢的原因是它所指向的对象如果被销毁 , 它会指向 nil。而 nil 访问什么鬼都不会报野指针错误 .
weak 不增加对对象的引用计数,也不持有对象,因此不能决定对象的释放。它比 assign 多了一个功能,当对象消失后自动把指针变成 nil
copy( ARC/MRC )
1.copy 在 MRC 时是这样做的 release 旧对象( 旧对象计数器 -1 ) , copy 新对象( 新对象计数器 +1 ) , 然后指向新对象 .(新对象是指最终指向的那个对象,不管深拷贝还是浅拷贝)
1.1在set方法里面是这样的 :
if (_dog) {
[_dog release];
}
_dog = [dog copy];
2.copy 在 ARC 时是这么干的 copy 新对象( 新对象计数器 +1 ) , 然后指向新对象 .
2.1在set方法里面是这样的 :
_dog = [dog copy];
3.使用注意 :
3.1 修饰的属性本身要不可变的 . 例如 NSMutableArray 采用 copy 修饰 , 添加元素表面上可以 一到运行就崩溃了 , 因为 copy 过后实际上成了NSArray了 . ( 队友 , 我们不吭你 )
3.2 遵守 NSCopying 协议的对象使用 .
建立一个索引计数为 1 的对象 然后释放旧对象 对 NSString 它指出 ,在赋值时使用传入值的一份拷贝 ,拷贝工作由 copy 方法执行,此属性只对那些实行了 NSCopying 协议的对象类型有效。
-
nonatomic ( ARC/MRC )
1.不对set方法加锁 .
2.性能好
3.线程不安全 -
atomic ( ARC/MRC )
1.原子属性就是对生成的 set 方法加互斥锁 @synchronized(锁对象) .
@synchronized(self) { _delegate = delegate; }
2.需要消耗系统资源 .
3.互斥锁是利用线程同步实现的 , 意在保证同一时间只有一个线程调用 set 方法 .
4.其实还有 get 方法 , 要是同时 set 和 get 一起调用还是会有问题的 . 所以即使用了 atomic 修饰 还是不够安全 .