历史由来:

接触iOS的人都知道,@property声明的属性默认会生成一个_类型的成员变量,同时也会生成setter/getter方法。 
但这只是在iOS5之后,苹果推出的一个新机制。看老代码时,经常看到一个大括号里面定义了成员变量,同时用了@property声明,而且还在@implementation中使用@synthesize方法。 
如下:

@interface ViewController ()
{// 1.声明成员变量NSString *myString; } //2.在用@property @property(nonatomic, copy) NSString *myString; @end @implementation ViewController //3.最后在@implementation中用synthesize生成set方法 @synthesize myString; @end

其实,发生这种状况根本原因是苹果将默认编译器从GCC转换为LLVM(low level virtual machine),才不再需要为属性声明实例变量了。

在没有更改之前,属性的正常写法需要成员变量+ @property + @synthesize 成员变量三个步骤。 
如果我们只写成员变量+ @property:

@interface GBViewController :UIViewController
{NSString *myString; } @property (nonatomic, strong) NSString *myString; @end
编译时会报警告:
Autosynthesized property 'myString' will use synthesized instance variable '_myString', not existing instance variable 'myString'

但更换为LLVM之后,编译器在编译过程中发现没有新的实例变量后,就会生成一个下划线开头的实例变量。因此现在我们不必在声明一个实例变量。(注意:==是不必要,不是不可以==) 
当然我们也熟知,@property声明的属性不仅仅默认给我们生成一个_类型的成员变量,同时也会生成setter/getter方法。

.m文件中,编译器也会自动的生成一个实例变量_myString。那么在.m文件中可以直接的使用_myString实例变量,也可以通过属性self.myString.都是一样的。

注意这里的self.myString其实是调用的myString属性的setter/getter方法。这与C++中点的使用是有区别的,C++中的点可以直接访问成员变量(也就是实例变量)。

例如在oc中有如下代码

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

在这段代码里面只是声明了一个成员变量,并没有setter/getter方法。所以访问成员变量时,可以直接访问name,也可以像C++一样用self->name来访问,但绝对不能用self.name来访问。

  • 扩展:很多人觉得OC中的点语法比较奇怪,实际是OC设计人员有意为之。
  • 点表达式(.)看起来与C语言中的结构体访问以及java语言汇总的对象访问有点类似,如果点表达式出现在等号  左边,调用该属性名称的setter方法。如果点表达式出现在右边,调用该属性名称的getter方法。
  • OC中点表达式(.)其实就是调用对象的settergetter方法的一种快捷方式,self.myString = @"张三";实际就是[self setmyString:@"张三"];

首先我们要明白,@synthesize 生成了setter/getter方法。 
虽然现在直接使用@property时,编译器会自动为你生成以下划线开头的实例变量_myString,不需要自己手动再去写实例变量。而且也不在.m文件中通过@synthesize myString;生成setter/getter方法。但在看老代码的时候,我们依旧可以看到有人使用成员变量+ @synthesize 成员变量的形式。

那么问题来了: 
我们能否认为新编译器LLVM下的@property == 老编译器GCC的 成员变量+ @property + @synthesize 成员变量呢?

答案是否定的。 
因为成员变量+ @property + @synthesize 成员变量的形式,编译器不会帮我们生成_成员变量,因此不会操作_成员变量了; 
同时@synthesize 还有一个作用,可以指定与属性对应的实例变量, 
例如@synthesize myString = xxx; 
那么self.myString其实是操作的实例变量xxx,而非_String了。  

三、类别中的属性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方法。

  注意一点,匿名类别(匿名扩展)是可以添加实例变量的,非匿名类别是不能添加实例变量的,只能添加方法,或者属性(其实也是方法)。

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

@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方法)。当然,你可以设置只读或者可写等,设置方法也可自定义。所以,属性变量是用于与其他对象交互的变量。

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

  但是,现在大家似乎都不怎么喜欢用成员变量来定义类的变量,都喜欢用属性变量来定义类的变量。把需要与外部接触的变量定义在.h文件中,只在本类中使用的变量定义在.m文件中。

首先来区别一下实例变量、成员变量的区别:
可以看到在接口 @interface 括号里面的统称为”成员变量”,实例变量是成员变量中的一种!
实例变量的英文翻译是 Instance Variable (object-specific storage) 
实例的英文翻译为Instance(manifestation  of a  class)  说的是“类的表现”,说明实例变量应该是由类定义的变量!
除去基本数据类型int float ....等,其他类型的变量都叫做实例变量。
**实例变量+基本数据类型变量=成员变量**
接下来说说属性:
 
在@property(描述1 , 描述2 , 描述3)(class *) varName 里面,有3个描述词需要填写(也可以不填写取默认值)
1. nonatomic<-->atomic
2. readwrite<-->readonly
3. retain/copy/assign
 
首先来介绍一下:
retain:他指的是将某个内存区域的指针赋值给变量,同时把该内存区域的引用计数器加1.每执行一次,该内存区域的引用计数器就要加1,当该区域的引用计数器变为0的时候内存区域被释放!
 
copy:它指的是将目标内存区域的值复制一份,然后开辟新的内存区域(新的指针)粘贴这个值。同时变量被赋值为新内存区域的指针!
 
assign:它指的是,仅只把目标内存区域的指针赋值给变量,该内存区域的引用计数器不发生变化!
 
1、2两点不做解释,3中的retain、copy、assign都是指的,在自动生成setter函数的时候,编译器需要识别个描述词来生成对应的setter函数!需要注意的是,如果没有加上该类的描述词,系统默认该变量的setter方法采取assign的方式。
在头文件中.h一般在{}里面会有定义的实例变量  
示例:
.h
@property (automic,retain) NSString * abc;
.m
@sythesize abc;

//在写了@sythesize abc;的情况下,系统不会自动生成实例变量“_abc”,直接通过变量名abc ,也就是直接使用变量名在赋值运算的时候(=号左边),只是将内存区域的指针赋值给变量,相当于assgin.   如果是通过“点语句”self.abc= 来赋值,就要看在@property中定义的是copy、retain、assign哪一种了,如果没有加上上述描述词,就默认为assign。

//如果没有写@sythesize abc;  系统会默认自动在.h文件{}中添加一个 不可见的 加“_”的成员变量(即使是变量名中本身就带有“_”)

//括号里面定义的都是成员变量(基本数据类型+类生成变量),里面的变量可以在.m文件中通过“变量名称”、self->“变量名称”直接访问到括号里面的变量,但是,这样的赋值访问只能是assign,原对象的引用计数器不会发生变化。

//1.@sythesize 变量名;2.@sythesize 变量名=_变量名;3.不写@sythesize (一下提到的变量名都是指的在头文件中@property 中定义的变量)

1.成员变量,实例变量通过“变量名”或者self->“变量名”直接访问到,赋值(assign)。self.变量名 实现setter,getter方法。

2.成员变量,实例变量通过“_变量名”或者self->“_变量名”直接访问到,赋值(assign)。self.变量名 实现setter,getter方法。

3.成员变量。实例变量(系统自动在原来变量名前加上“_”来生成的实例,成员变量),直接通过self->_变量名,或者变量名直接访问到(assign)。self.变量名 实现setter,getter方法。

如果在头文件中没有通过@property定义的变量,但是在{}中有定义成员变量,在实现文件中也也没有@sythesize ,那么可以直接通过self->“{}中的变量名”,或者直接使用“{}中的变量名”来访问赋值,这样的变量没有定义setter,getter函数,只能是assign的方式赋值。

//再来分析一下@sythesize中的写法,@sythesize abc 直接在.m文件中使用self.abc可以调用成员变量的setter、getter函数,直接调用成员变量名称abc就为访问该变量的指针,对成员变量直接赋值等同于ASSIGN效果。

参考:
http://blog.csdn.net/u012946824/article/details/51788565
http://www.cnblogs.com/AnnieBabygn/p/5335350.html

转载于:https://www.cnblogs.com/huangzs/p/7508583.html

成员变量和属性区别(@property那点事儿)相关推荐

  1. java中的成员变量和局部变量的区别_java中成员变量与局部变量区别分析

    本文实例分析了java中成员变量与局部变量区别.分享给大家供大家参考.具体分析如下: 成员变量:在这个类里定义的私有变量,属于这个类. 创建以及使用成员变量 public class Person { ...

  2. OC 成员变量和属性的区别 .

    转自:http://blog.sina.com.cn/s/blog_727bd1560101llwj.html 比如下面这个程序,aboutList,和 otherList 到底有什么不同, @int ...

  3. Java成员变量和属性的区别与联系

    成员变量有多种访问控制符,通常都应该把成员变量定义成私有的private ,然后为该成员变量提供set方法和get方法,外界只通过set方法和get方法对成员变量进行操作,这样也体现了面向对象的三大特 ...

  4. 20、成员变量和属性

    成员变量 属性 区别:类内使用成员变量,类外使用属性 属性是成员变量的外部接口,属性为了让类外可以访问成员变量 比如:姓名.年龄.性别,都是人固有的,是成员变量 再比如: People.h #impo ...

  5. java什么是局部变量_java局部变量是什么意思?Java中局部变量与成员变量有哪些区别?...

    大家知道Java中的局部变量吗?今天我们要了解的Java的局部变量及它和成员变量的区别,一起来看看吧. 什么是局部变量? 局部变量时就是只有一部分可见的变量,例如定义在方法中的变量,只有这百个方法才能 ...

  6. Java静态变量与静态方法与成员变量成员方法的区别

    java变量分为实例变量和静态变量方法分为实例方法和静态方法 如 class Example{ int data;//定义实例变量,也叫成员变量 public void method(){     / ...

  7. java static成员变量方法和非static成员变量方法的区别 ( 二 )

    原创文章,未经作者允许,禁止转载!!! 静态成员变量不用new对象,在类加载的过程中就已经初始化存放在数据区域,静态成员变量是类和所有对象共有的, 类和对象都可以改变它的值,每一次改变值之后,静态成员 ...

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

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

  9. Delegate成员变量和Event的区别

    上周五有同事问了我一个问题:Delegate和Event有什么区别?具体来说在设计一个类的时候,声明一个事件(Event)和声明一个Delegate类型的成员变量有啥区别. 我的第一反应是没啥区别,虽 ...

最新文章

  1. 浏览器无法访问虚拟机的服务器
  2. js实现的简单模态对话框
  3. IsWindow函数的作用
  4. 学习分布式不得不会的ACP理论
  5. bootstrap-table之通用方法( 时间控件,导出,动态下拉框, 表单验证 ,选中与获取信息)
  6. linux添加定时器防抖,linux驱动2.3按键中断-定时器防抖
  7. ES7新特性_介绍--JavaScript_ECMAScript_ES6-ES11新特性工作笔记047
  8. windows下使用Wireshark调试chrome浏览器的HTTP/2流量
  9. android 启动界面修改工具下载,安卓开机画面更改软件
  10. 大神u盘工具(win10PE)UEFI纯净版启动盘制作工具
  11. 机械设计:机械加工中获得工件尺寸精度的常用方法!
  12. html表格外边框粗细,table细边框
  13. paypal/stripe商家工具-轮询支付系统更新
  14. 使用命令行操作Windows防火墙
  15. Valley Numer
  16. HTML语言中img标签的alt属性和title属性的作用与区别
  17. win10-SW2016工程图关联零件属性链接操作
  18. 现在爆火的数字孪生城市,到底是什么技术?
  19. xxl-job远程命令执行漏洞复现
  20. C++-顺序栈实现10进制转换为2、8、16进制(详细)

热门文章

  1. Oracle 查看sql语句执行计划方法
  2. 转: Linux 下修改oracle 的字符集:WE8ISO8859P1 修改为 ZHS16GBK
  3. java8生成jsp页面内容组装到jsp中_JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构、调试、部署...
  4. JVM监控及诊断工具-命令行篇一
  5. c语言程序设计棋盘不对齐,经典c语言程序设计例(55页)-原创力文档
  6. sqlmap代理池_sqlmap +外部代理池绕过IP拦截
  7. python爬虫基础教程115_Python解析网页源代码中的115网盘链接实例
  8. 聚焦云原生,阿里云与 CNCF 共话「云未来,新可能」
  9. OpenYurt 开箱测评 | 一键让原生 K8s 集群具备边缘计算能力
  10. 黑php的称呼,称呼