您的位置:首页 > 其它

OC中属性和成员变量的区别和使用

2015-08-05 23:59 267 查看
    当我们在一个程序中声明一个变量,是将它声明为成员变量呢还是封装成属性呢?

    上网查了一查,再加上自己的理解,整理如下:

    

    首先分别介绍一下成员变量和属性

    1) 成员变量 如下一段代码

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
@private
NSString * _name;
}

@end
    成员变量声明在 @interface 和 @end 中间,并用大括号 { } 与成员方法加以区分。

    上图例示就是在类 Person 中声明了一个字符串类型成员变量 _name。

    在OC中人为规定成员变量前面添加一个下划线 _  原因后面介绍到属性的时候会进行阐述 (如果写到后面还没有忘记的话)。

    成员变量上面顶着的 @private 是对成员变量的作用域的声明。

    @private 指的是私有成员,@private 标示的成员变量只能有类实例化的对象本身所调用。相对还有可以在有继承关系的子类中访问的 @protected 标识符和可以任意访问的 @public 标识符。默认情况下(不写作用域)是 @private。出于类的封装等方面考虑,建议对成员变量使用 @private。

   创建的成员变量可以在类中的方法直接进行访问,如下示例:

#import "Person.h"

@implementation Person

- (void)setPersonName {
_name = @"张三";
}

@end
    上例是对类 Person 中的成员变量进行赋值操作。

    因为是私有的成员变量,所以没办法直接在类外面访问。需要在类中定义相关方法来实现成员变量的获取和赋值。如下例:

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
@private
NSString * _name;
}

- (void)setName:(NSString *)name;
- (NSString *)getName;

@end
#import "Person.h"

@implementation Person

- (void)setName:(NSString *)name {
_name = name;
}

- (NSString *)getName {
return _name;
}

@end
#import <Foundation/Foundation.h>
#import "Person.h"

int main() {

Person * p = [[Person alloc] init];

[p setName:@"李四"];
NSString * lisiName = [p getName];

NSLog(@"%@", lisiName);

return 0;
}
    上例中,在 .h 文件中声明了对成员变量 _name 的赋值和获取方法以供类外部调用,同时在 .m 文件中实现相关方法。

    在main函数中实例化 Person 类,调用setName函数为对象 p 的成员变量 _name 赋值,然后获取到这个值,再进行打印输出。

    以上是成员变量的创建和使用。

    有时候我们需要在一个类中创建十多个成员变量,这就意味着需要写双倍的set和get方法来供外部访问这些成员变量,而且set和get方法格式内容大都相同。

    OC中提供了一种称为属性的结构来简化这一过程。

    2) 属性

    首先来看一个例子,同样是定义一个成员变量,我们还可以通过以下定义属性来达到相同的目的:

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property NSString * name;

@end
#import "Person.h"

@implementation Person

@synthesize name = _name;

@end
    上例中,在 .h 文件中使用 @property 关键字定义了一个属性,名字是 name 。

    系统会检查类中是否有同名的成员变量,如果没有,则会隐式的帮助声明一个成员变量 _name 。 这一点最直观的体现就是即使没有人为声明成员变量 _name,在类中的方法也可以赋值或者调用 _name。除此之外,系统还会在 .h 文件中为类隐式的声明get和set方法。set 方法的格式就是在首字母大写的属性名前面加上 set ,get 方法直接以属性名来命名。

    而在 .m 文件中,可以使用关键字 @synthesize 来对属性进行绑定。@synthesize 关键字后面紧跟着的是属性名字,等号后面即为该属性所绑定的成员变量。该关键字的作用是在 .m 中对set和get方法进行实现。具体实现格式与上面格式的例子差不多(不考虑内存管理的时候)

    在较新的版本中,关键字 @synthesize 可以省略,仅使用 @property 关键字就可以完成成员变量和 set get 方法对创建。

    在调用方面,使用属性定义的成员变量,可以使用 set get 方法调用,也可以使用点语法调用。因为属性隐式生成的成员变量是@private类型的,所以并不能直接使用->来调用。示例如下:

#import <Foundation/Foundation.h>
#import "Person.h"

int main() {

Person * p = [[Person alloc] init];

[p setName:@"李四"];

NSLog(@"%@", [p name]);

return 0;
}
    实现结果和上一个是一样一样的。

    从上面的比较来看,省时省力省行数的属性似乎应该更有使用价值。但是我们依然可以通过手动来定义成员变量。所谓万事皆有因。下面来说说成员变量的属性的使用场合。

    定义属性的目的是为了对外部提供一个访问类内部私有成员变量的接口。这就意味着这些定义的属性对外部是敞开的,当然我们也可以通过对属性进行设置来使其只提供 get 方法等确保数据安全稳定。但是,当我们希望仅仅在这个类中的不同方法中共享一个变量而不希望对被外部所看到时候,定义属性未免太过浪费和不合适。这时候就体现到成员变量的优势。而在 .m 中也可以定义成员变量更是极大避免了代码正码到激情四射时候需要切换文件的不爽。

 ----------

    综上所述,属性是在希望展示给类外部的类本身属性时候创建,成员变量则是在类内部需要共享访问时候创建。

    以上内容仅代表个人观点。如有错误欢迎指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OC 变量