iOS进阶之iOS中实例变量与属性的区别(7)

前言

在编写OC代码时,我们已经很熟练了使用@property关键字声明属性,以及如下声明实例变量:

@interface MyViewController :UIViewController
{
    NSString *name;
}
@end

但是这两者的区别不是很清楚,只知其然不知所以然。以及涉及到setter、getter 方法声明。今天就从新深刻学习一下。

@property关键字声明属性

@property (nonatomic, copy)NSString *userName;

声明属性,让编译器在.m文件里生成_userName 对应的实例变量;生成实例变量对应的setter和getter方法,至于.m文件中的@synthesize userName;就不要写了,它的作用就是为实例变量生成setter和getter方法,现在可以不用写它了,但是如果你想重写setter和getter方法。在.m文件中仍然需要@synthesize userName

@synthesize

@synthesize 还有一个作用,可以指定与属性对应的实例变量,例如@synthesize myButton = xxx;那么self.myButton其实是操作的实例变量xxx,而不是_myButton了。

在实际的项目中,我们一般这么写.m文件

@synthesize myButton;这样写了之后,那么编译器会自动生成myButton的实例变量,以及相应的getter和setter方法。注意:_myButton这个实例变量是不存在的,因为自动生成的实例变量为myButton而不是_myButton,所以现在@synthesize的作用就相当于指定实例变量;

如果.m文件中写了@synthesize myButton;那么生成的实例变量就是myButton;如果没写@synthesize myButton;那么生成的实例变量就是_myButton。所以跟以前的用法还是有点细微的区别。

  • @synthesize age = _age;
    setter和getter实现中会访问成员变量_age
    如果成员变量_age不存在,就会自动生成一个@private的成员变量_age
  • @synthesize age;
    setter和getter实现中会访问@synthesize后同名成员变量age
    如果成员变量age不存在,就会自动生成一个@private的成员变量age

还有一个作用,可以指定与属性对应的实例变量, 例如@synthesize str =
xxx;那么self.str其实是操作的实例变量xxx,而不是_str了。 如果.m文件中写了@synthesize
str;那么生成的实例变量就是str;如果没写@synthesize str;那么生成的实例变量就是_str。

类别中的属性property

类与类别中添加的属性要区分开来,因为类别中只能添加方法,不能添加实例变量。经常会在ios的代码中看到在类别中添加属性,这种情况下,是不会自动生成实例变量的。比如在:UINavigationController.h文件中会对UIViewController类进行扩展

@interface UIViewController (UINavigationControllerItem)

    @property(nonatomic,readonly,retain) UINavigationItem *navigationItem;
    @property(nonatomic) BOOL hidesBottomBarWhenPushed;
    @property(nonatomic,readonly,retain) UINavigationController *navigationController;
    
@end

这里添加的属性,不会自动生成实例变量,这里添加的属性其实是添加的getter与setter方法。注意一点,匿名类别(匿名扩展)是可以添加实例变量的,非匿名类别是不能添加实例变量的,只能添加方法,或者属性(其实也是方法)。

@property的作用

使用@property的好处是:免去我们手工书写getter和setter方法繁琐的代码
属性:就是通过(getter/setter)方法,去访问生成的同名的_实例变量。这个_实例变量是@protected。通过点调用访问_实例变量。
实例变量:就是一个变量,如果没有(getter/setter)方法,是不能打点访问的。
所以说一个类,实际上只有成员变量和方法。属性只是提供了一种打点便捷访问成员变量的一种形式。

(1)生成了私有的带下划线的的成员变量因此子类不可以直接访问,但是可以通过get/set方法访问。
(2)@property用在声明文件中告诉编译器声明成员变量的访问器(getter/setter)方法。

  • @property (nonatomic, copy) NSString *str;这句话完成了3个功能:
    1)生成_str成员变量的get和set方法的声明;
    2)生成_str成员变量set和get方法的实现;
    3)生成一个_str的成员变量。(注意:这种方式生成的成员变量是private的)

setter和getter方法

setter方法作用

  • 用来设置成员变量,给成员变量赋值,可以在方法里面对变量进行判断,过滤掉一些不合理的值

setter方法的好处

  • 不让数据暴露在外,保证了数据的安全性
  • 对设置的数据进行判断,过滤不合理的值(比如空值、负数等等)

getter方法作用

  • 为调用者返回对象内部的成员变量的值,用来访问成员变量

getter方法的优点:

  • 可以让我们在使用getter方法获取数据之前,对数据进行加工
  • 比如双十一活动,我们希望对全线商品的价格在原来的价格基础上打五折,那么我们只要去改成品类的价格的getter方法就可以了,让他返回的值为价格 * 0.5
- 如果想对传入的数据进行过滤,那么我们就必须重写getter/setter方法
- 如果同时重写了getter/setter方法,那么property就不会自动帮我们生成_开头的成员变量(报错)
- 如果利用@property来生成getter/setter方法,那么我们可以不写成员变量, 系统会自动给我们生成一个_开头的成员变量

点语法

  1. 点语法基本使用

如果给成员变量提供了getter和setter方法,就可以通过点语法来访问成员变量

  1. 点语法的本质
  • 其实点语法的本质就是调用了setter方法和getter方法
  • 当使用点语法时,编译器会在程序翻译成二进制的时候将.语法自动转换为setter和getter方法
  • 如果点语法在=号左边,那么编译器会自动转换为setter方法
  • 如果点语法在=号右边,或者没有等号,那么编译器就会自动转换为getter方法
  1. 点语法注意
  • 点语法的本质是方法的调用,而不是访问成员变量,当使用点语法时,编译器会自动展开成相应的方法调用
  • 如果没有setter和getter方法,则不能使用点语法
  • 不要在setter与getter方法中使用本属性的点语法

成员变量、实例变量、属性变量的联系

@interface MyViewController :UIViewControlle
{

UIButton *yourButton;
int count;
id data;

}
@property (nonatomic, strong) UIButton *myButton;
@end

在{ } 中所声明的变量都为成员变量。 所以yourButton、count、data都是成员变量。既然如此,实例变量又是什么意思呢?实例变量本质上就是成员变量,只是实例是针对类而言,实例是指类的声明。{ }中的yourButton就是实例变量。id 是OC特有的类,本质上讲id等同于(void *)。所以id data属于实例变量。

成员变量用于类内部,无需与外界接触的变量。因为成员变量不会生成set、get方法,所以外界无法与成员变量接触。根据成员变量的私有性,为了方便访问,所以就有了属性变量。属性变量的好处就是允许让其他对象访问到该变量(因为属性创建过程中自动产生了set 和get方法)。当然,你可以设置只读或者可写等,设置方法也可自定义。所以,属性变量是用于与其他对象交互的变量。

综上所述可知:成员变量是定义在{}号中的变量,如果变量的数据类型是一个类则称这个变量为实例变量。因为实例变量是成员变量的一种特殊情况,所以实例变量也是类内部使用的,无需与外部接触的变量,这个也就是所谓的类私有变量。而属性变量是用于与其他对象交互的变量。

参考

iOS 开发:成员变量(属性,实例变量)的相关知识

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值