OC的属性
OC的属性机制提供了一个默认的设置器和访问器的实现
现在先了解OC的实例变量作用域。
@protected: 受保护的,这个实例变量只能在该类和这个类的子类中被访问,(可以被子类继承)其他类无法访问。不写的情况下默认为这个属性。
@private:私有的,这个实例变量只能再该类的中访问,其他类不能访问,包括它的子类继承同样无法访问
@public:公有的,这实例变量谁都能访问。
新建一个项目用来测试变量的作用域
新建一个Student类
新建Student类
接下来在接口文件中定义实例变量
Student.h
接下来在创建一个SmallStudent类文件,继承自Sutudent类
新建类
接口文件中查看继承
在子类文件中的接口文件做一个测试方法test声明
SmallStudent.h
在子类文件中实现文件.m做测试方法的操作
-在文件中可以看到,子类可以使用父类中的公有的,和受保护的实例变量,但是无法使用父类中私有的实例变量。
-在编辑的时候有有错误的提示,在实例变量名上有一条红线,就是无法使用的表示。
Student.m
最后在main.m文件中在进行测试,记得添加头文件
main.c
受保护的实例变量只能在该类和继承的子类中使用,所以实例变量中只有公有的能被使用。
总结:
为了隐藏实例变量,我们可以使用@protected(受保护)和@private(私有)关键字。
通过类的实例变量的作用域来限制实例变量的访问范围。
现在使用设置器和访问器(存取的方法)访问实例变量
在使用@protected变量和@private实例变量的时候,要进行信息的交换,这是就需要用到存取方法(getter和setter)
取实例变量的值用getter方法
设定或修改变量的值用setter方法
新建项目,在项目中做一个Student的类
在类的接口文件中写两个私有的实例变量(默认不写就是私有的 和行为部分的方法
在类的实现文件中对方法进行重写和方法的具体实现
Student.m最后在mian.m文件中使用setter 和getter方法
main.m
总结:
-使用set和get 方法间接的方法来访问实例变量,在封装隐藏变量的同时,提供饿了访问的方法。
-同时,我们也可以在setter方法中(存方法)对实例变量的值进行合法性的的判定。
属性的定义和使用
使用setter(存方法)和getter(取方法)在数据量大的时候,不适合使用,因为需要手写许多的重复性的setter 和getter代码。这时就需要用到OC中自动产生getter和setter方法。这种方法就是属性。
同样的新建一个项目,在项目中同样新建一个Student类
在类的接口文件.h 中使用@property符号对方法进行声明。
@propert语句就相当于起到了getter和setter方法声明的作用
-基本类型的实例变量,只需要加上@property就可以了。
-如果需要的类型是哪类对象的实例变量,只需要加上相应的描述,如:
两个接口文件的对比(nonatomic,strong)
接下来在实现文件中,用@synthesize符号来是实现和替代相应的方法实现。
两个实现文件的对比@systhesize一条语句就祈祷了getter和setter的方法实行的作用。
最后,在mian.m 文件中实现。这里就便不再需要修改了。
mian.m
在这里还可以进行进一步的简化
类的接口文件中.h 中的实例变量声明可以省略。
Student.h
类的实现文件中.m 中@synthesize可以省略,修改重写方法
Student.m
因为把@synthesize注释掉了,系统会自动提供一个下划线开头的实例变量,因此,需要把类的实现文件中的市实例变量修改过来。
点语法
点语法和C语言的的结构体操作类似,只是操作类似,并不是C语言的结构体。
在mian.m文件中的操作可以用到点语法。
main.m
在类的文件中同样可以用点语法,这是就要使用self.
property的语法
存取方法
系统默认的的存取方法名propertyName和setPropertyName。
如:Student类中的name,对应的存取方法名称是name和setName。
getter=getterName
指定getter自定义方法的名称,自定义方法必须返回类型匹配的值,并且没有参数。
如:
@property(getter=getName)NSString *name;
setter=setterName
指定setter自定义方法的名称自定义方法必须只有一个类型匹配的参数,并且返回void。
如:
@property(setter=newSetName)NSString *name;
如果改变了getter和setter方法的名称,必须提供自定义的方法。
可读写性
可读写性确定了属性是否有setter方法。
readwrite
指明属性是可读写的(默认值),可省略不写
如:
@property(readwrite)NSString *name;
readonly
指明属性是只读的,系统会产生getter方法,不会产生setter方法。
如:
@property(readonly)NSString *name;
只读的属性,如果想通过点语法给它赋值,会得到编译错误。
setter语义
用于setter的方法,属于互斥的。
strong 表示强引用关系,拥有目标对象的所有权
weak 表示弱引用关系,不拥有目标对象的所有权。
当目标对象被销毁之后,属性值会被自动设为nil。
copy 会通过copy复制对象,之前的对象会接受到释放的信息。
assign 表明采用简单的赋值方法(默认方式)
retain 会通过retain来持有目标对象,之前的对象会接受到释放的消息。
原子操作
通过这些来判断是否采用了原子操作
atomic 原子操作,属于默认值。在多线程环境中,把方法设定为原子操作,可以提供 可靠的属性存取方法。
nonatomic 非原子操作,会简单的操作属性值。可以加快属性值存取的速度,但是无法保证在多线程环境下不会出错。
属性的重定义
可以通过重写把制度(readonly)的属性修改为可读写(readwrite)的。可以通过在延展协议和子类中重新定义。
重定义的应用模式
Student类接口文件.h 子类MutableStudent从一个不可变的父类产生可变的子类
一个类有只读的公开的属性和可读写的私有的属性
或者通过延展修改Student类,让Student拥有一个公开只读name,有一个私有的可读写的name
实行的使用过程中注意:
1.没使用@synthesize的时候,系统会自动生活城类似_name格式的变量,但是我们仍然使用name,这时的_name和name是两个不同的变量。
2.点语法中如果使用了C语言的结构体代码,当对象为nil的时候,调用C结构体会使程序崩溃。
3.系统自动产生的get方法,其实不是get开头的,如果使用类的aName =[stu1 get Name ];Xcode会警告,运行时会出错。