OC语言基础五:OC中的set和get方法,属性生成器,属性约束

本文深入探讨Objective-C中set和get方法的应用,属性生成器的便利性,以及不同属性约束如nonatomic、copy、strong等在内存管理和线程安全方面的考量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

set和get

在类的外部间接的完成对属性或者成员变量的赋值和取值操作。
好处是隐藏了具体的实现逻辑,对外提供接口,也方便类的使用者去赋值和取值操作,而且用接口去实现操作,会使代码的语义更加的明确。而直接访问成员变量会破坏代码的封装性.

类的成员变脸默认是受保护的,protected。如果要直接访问还要将它设为public.
set和get方法都是对象方法,也就是要-号开头的。类方法是无法直接访问属性和变量的。

语法

//Person.h
#import <Foundation/Foundation.h>
{
  NSString *_name;
  NSUInteger _age;
  NSString *_sex;
}
-(void)setName:(NSString *)name;
-(void)setAge:( NSUInteger *)age;
-(void)setSex:(NSString *)sex;
-(NSString *)name;
-(NSUInteger)age;
-(NSString*)sex;
@end

set赋值,set后接变量去掉下划线的名字,首字母大写,有参数,无返回。
get方法取值,就直接写变量去掉下划线的名字,首字母小写,无参数,有返回。

//Person.m
-(void)setName:(NSString *)name{
_name=name;
}
-(NSString *)name{
  return _name;
}
-(NSString *)description{
  return [NSString stringWithFormat:@"name=%@,age=%zd,sex=%@",_name,_age,_sex];
}

使用:
Person *person =[[Person alloc]init];
[person setName:@“张三”];
或者person.name=@“张三”;
NSLog("%@",person);
NSString *age=[person age];
或者NSString *age=person.age;

将.语法读成的就好理解了。

属性生成器

有了属性生成器后,它会自动生成set和get方法,和生成带下划线的成员变量。

//Person.h
#import <Foundation/Foundation.h>
//{
//  NSString *_name;
//  NSUInteger _age;
//  NSString *_sex;
//}
@property NSString *name;
@property NSUInteger age;
@property  NSString *sex;

属性约束

在运用属性生成器去生成属性的时候,对其进行的约束和控制。
1.线程安全相关(原子性)
atomic (原子操作)(默认)
nonatomic(非原子操作)
线程安全在多线程操作的时候可能出现一种资源掠夺的情况,可能导致多个线程下对同一个属性同时进行一个值的修改或者其他操作,就会导致意想不到的效果,所以添加一个限制,即atomic原子操作来防止这种情况的出现。
一般也不会以牺牲程序的执行效率为代价去使用atomic。 要想保证属性是线程安全的,有其他方式对其进行控制,更应该代码的良好编程去保证线程的安全,而不是通过这样的设置手段,所以一般我们都使用nonatomic.

2.内存管理相关
MRC下,retain(强引用),copy(强引用),assign(弱引用,赋值,默认)
copy和retain的区别,copy的操作多了一步,它对对象进行拷贝操作,而retain并不会这样去做。
对基本数据类型的属性来进行一个赋值操作,那我们要使用assign。
ARC下,strong(强引用),weak(弱引用)
同时出了retain以外,copy和assign在ARC下也可以使用。
assign和weak在ARC下的区别:当我们使用assign的时候,如果一个对象释放了以后,当前指向这个对象的对象指针依然会保留着我们这个对象的内存地址,如果继续使用这个指针就会导致内存崩溃,因为去访问了非法的内存空间。当使用weak的时候,当对象释放以后,相对应地对象指针也会被置为nil,后续再拿它进行操作是没有任何意义的。所以ARC下表示弱引用尽量使用weak。只有对基本数据类型的属性进行约束控制的时候才使用assign。

3.读写属性相关:
readwrite(同时生成setter和getter方法)(默认)
readonly(只生成getter方法)

如果只希望通过属性生成器来获取我们属性的值,而不希望我们外界去修改类中的值,就需要用到readonly。

4.重命名相关
setter方法重命名 方法名称后必须附带一个。
getter方法重命名。

copy

当修饰可变类型的属性时,如NSMutableArray、NSMutableDictionary、NSMutableString,用strong。

当修饰不可变类型的属性时,如NSArray、NSDictionary、NSString,用copy。

@property(nonatomic,copy)NSString *sex
.......
NSString *sex=@"男";
person.sex=sex;
NSLog("%p %p",person.sex,sex);

person.sex 和sex是相同的地址。这是因为字符串的特殊性,字符串的创建非常消耗内存资源,所以提供了享元模式,就是每次当我们创建一个字符串常量的时候都会放在一个缓冲区里面,下次再取的时候就会从缓冲区里面进行取出。

@property(nonatomic,copy)NSMutableString *sex
.......
NSMutableString *sex=[NSMutableString stringWithString:@"男"];
person.sex=sex;
NSLog("%p %p",person.sex,sex);
此时person.sex 和sex是不同的地址。

重命名

@property(nonatomic,strong,setter=setPersonName:)NSString *name;
......
-(void)setPersonName:name{
_name=name;
}

setName就已经被替换了,不存在了,被替换成了setPersonName
点语法去调的话也会去调setPersonName。
NSLog(@"%@",func);可以打印当前函数的名字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值