成员变量和属性区别(@property那点事儿)
历史由来:
接触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中
点表达式(.)
其实就是调用对象的setter
和getter
方法的一种快捷方式,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文件中。
//在写了@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效果。
成员变量和属性区别(@property那点事儿)的更多相关文章
- iOS中成员变量和属性区别
历史由来: 接触iOS的人都知道,@property声明的属性默认会生成一个_类型的成员变量,同时也会生成setter/getter方法. 但这只是在iOS5之后,苹果推出的一个新机制.看老代码时,经 ...
- C# 成员变量和属性的区别
之前一直在C#中使用这两者, 却一直不知道成员变量和属性还是不一样的两种概念. 不过说不一样, 也不是完全对. 简单举个例子: public class myclass { public string ...
- OC基础成员变量、属性变量、实例方法与类方法
首先,为什么我们要定义一个新类呢?按照我的理解,就是为了抽象出来一个新的东西(也就是类),用来存储更多的数据变量和方法,一切类都直接或间接继承与NSObject. 在类的头文件里我们可以定义成员变量. ...
- runtime第二部分成员变量和属性
接上一篇 http://www.cnblogs.com/ddavidXu/p/5912306.html 转载来源http://www.jianshu.com/p/6b905584f536 http:/ ...
- Objective-C Runtime 运行时之二:成员变量与属性
类型编码(Type Encoding) 作为对Runtime的补充,编译器将每个方法的返回值和参数类型编码为一个字符串,并将其与方法的selector关联在一起.这种编码方案在其它情况下也是非常有用的 ...
- Objective-C Runtime 运行时之二:成员变量与属性(转载)
在前面一篇文章中,我们介绍了Runtime中与类和对象相关的内容,从这章开始,我们将讨论类实现细节相关的内容,主要包括类中成员变量,属性,方法,协议与分类的实现. 本章的主要内容将聚集在Runtime ...
- 刨根问底Objective-C Runtime(4)- 成员变量与属性
http://chun.tips/blog/2014/11/08/bao-gen-wen-di-objective[nil]c-runtime(4)[nil]-cheng-yuan-bian-lian ...
- JAVA中局部变量 和 成员变量有哪些区别
JAVA中局部变量 和 成员变量有哪些区别 1.定义的位置不一样<重点>***局部变量:在方法的内部成员变量:在方法的外部,直接写在类当中 2.作用范围不一样<重点>***局部 ...
- Java成员变量和局部变量区别
成员变量和局部变量区别 变量根据定义位置的不同,我们给变量起了不同的名字.如下图所示: 区别 在类中的位置不同 (重点) 成员变量:类中,方法外 局部变量:方法中或者方法声明上(形式参数) 作用范围 ...
随机推荐
- Spark资源管理
Spark资源管理 1.介绍 Spark资源管控分为spark集群自身可支配资源配置和job所用资源配置. 2.spark集群支配资源控制 在spark的conf/spark-env.sh文件中可以指 ...
- Linux远程桌面(三)
上一篇中的vnc配置已经很方便了,这一篇介绍更为简单的xmanager的配置,xmanager画面好一丢丢. Xmanager服务器配置 Linux远程桌面(二):vnc之xi ...
- 在你的andorid设备上运行netcore (Linux Deploy)
最近注意到.net core 的新版本已经开始支持ARM 平台的CPU, 特意去Linux Deploy 中尝试了一下,真的可以运行 Welcome to Ubuntu 16.04 LTS (GNU/ ...
- C++学习之拷贝构造函数
嘛是拷贝构造函数? 如果一个构造函数的第一个参数是’自身类‘ ‘类型’的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数.如: [代码1] 1 2 3 4 5 6 class A{ publ ...
- Jenkins添加项目说明,增加项目描述
背景:往往正常Jenkins上呈现的内容,太过简短,不易直观看了解项目是干嘛的,如下面的内容: 解决方案,使用插件,Extra Columns Plugin 安装成功后配置,需要结合自定义视图使用,新 ...
- Linux ELF格式分析
http://www.cnblogs.com/hzl6255/p/3312262.html ELF, Executable and Linking Format, 是一种用于可执行文件.目标文件.共享 ...
- Poj(1521),哈夫曼编码
题目链接:http://poj.org/problem?id=1521 这里,网上有很多博客都有写,很多人没有建树,直接就是求一下这个哈夫曼编码的长度,的确很巧妙,我也用的这个方法,但是,几乎所有博客 ...
- Maven 配置本地依赖jar
现有json-1.0.jar,引入依赖方法如下: 1. 在项目下新建 lib 目录,复制json-1.0.jar到lib目录下 pom.xml中添加配置 <dependency> < ...
- Mathematica 讲座
Mathematica 讲座笔记本 [下载] 第一章 Mathematica 简介 [观看] [下载] 第二章 Mathematica 界面和编程语言 [观看] [下载] 第三章 符号运算 [观看] ...
- skimage.io.imread vs caffe.io.load_image
这两周在跑一个模型,我真的是被折腾的要崩溃了. 最后原因就是数据类型的问题,你说是不是应该管小黑屋啊. skimage.io.imread得到的是uint8的数据,而caffe.io.load_ima ...