黑马程序员——ObjC基础—属性及封装

来源:互联网 发布:软件开发数学 编辑:程序博客网 时间:2024/05/17 06:00
-----------Java培训、Android培训、IOS培训、.Net培训、期待与您交流!------------ 
本节学习OC中的属性封装。

1、什么是属性封装
在设计语言中,封装是一个很大的概念,泛指那些将具体功能实现继承到一个模块,只关注模块使用的一种思想,本节要学习的属性封装,指的是对OC对象内部的属性进行私有化,外部通过对象方法来访问内部属性的一种做法。听起来很绕,这有什么意义呢?我们慢慢讨论:

2、怎么封装?
前面已经说过了,我们可以通过对象方法来设置对象的参数,直接看代码吧:
@interface Person : NSObject{    @private // 默认就是私有    /*     @private : 只能本类内部访问     @protected: 本类和子类内部访问     @public : 外部可访问     @package : 在一个框架内部相当于private,外部不可访问     */    NSString *_name; // 私有属性 _name(下划线为规范格式)    int _age; // 私有属性 _age(下划线为规范格式)}// set方法(设置属性,规范格式)- (void)setName:(NSString*)name;- (void)setAge:(int)age;// get方法(取得属性,规范格式)- (NSString*)name;- (int)age;@end@implementation Person// set方法- (void)setName:(NSString *)name{    // 此处插入参数过滤代码    _name = name;}- (void)setAge:(int)age{    // 此处插入参数过滤代码    _age = age;}// get方法- (NSString *)name{    return _name;}- (int)age{    return _age;}@end
在上面设计的Person类中,我们定义了名字(_name)和年龄两个属性(_age),如果我们通过:
    Person *p=[Person new];    p->_name=@"xxx"; // instance variable '_name' is protected
进行访问,会直接报错(属性为保护数据,无法访问),这个时候只能通过对象里的方法来操作属性:
    // 设置属性    [p setName:@"xiaoming"];    [p setAge:18];        // 访问属性    NSString *n = [p name];    int a = [p age];
我们也可以直接通过 点语法 来操作属性,这是xcode提供给我们的一套模仿c++和java的便捷方法,这其实是个文字游戏,最终还是转化为上面的方式,所以,没有按照格式写set方法,和get方法的话,是不能使用点语法的。
点语法操作如下:
    // 设置属性    p.name = @"xiaoming";    p.age = 18;        // 访问属性    NSString *n = p.name;    int a = p.age;

3、代码的简化
我们可以看到,通过这样的方式创建对象,需要编写大量的读写方法,而且这些方法大都结构相似,有经验的编程者都不喜欢做重复的东西,浪费大量的时间。xcode为了方便大家,让大家把更多的精力放在更重要的事情上,新添加了一些优化指令,以帮助我们自动生成读写方法。
我们看看上面的Person对象通过优化指令来写,又是什么样子:

@interface Person : NSObject@property NSString *name;@property int age;@end@implementation Person@synthesize name=_name; // (Xcode4.4版本以后可省略)@synthesize age=_age; // (Xcode4.4版本以后可省略)@end
是不是变得异常简单了?很明显,我们在编写开头那个Person对象的时候,也只是设计了两个属性,没有实质性的工作,xcode把我们的代码优化到了只剩下name,age两个自定义的名称(注意这里不写下划线,但是实际产生的带下划线),也是可以理解的。而实现部分,xcode4.4版本以后已经被优化没了。
注意点:
① 这里的优化,并不是说不需要上面的set方法,get方法,而是xcode代替我们写这些代码,我们在调试的时候,会发现,xcode会自动把这些优化指令展开成开头我们设计的Person类的样子,几乎是完全一样的,这是因为,在开头的地方,我刻意采用了和xcode展开指令相同的方式来设计Person类,这是一个好习惯和好的规范。
② @property指令会检测我们有没自己创建同名(带下划线)属性,当检测到的时候,自动调用,并生成set方法和get方法;当没找到时,会自动生成,注意这里生成的是private类型的属性。同时,对于set方法和get方法也是如此。
③ 我们可以通过@synthesize指令更改属性的名称,但是我们不建议这样做,大家统一用下划线格式。
④ 在@property指令里,还可以带一些参数,以实现更个性化的要求,列举如下:
@property (getter = getName1) NSString *name1; // 更改getter方法的名字(setter = xxxx 也可以)@property (readonly) NSString *name2; // 只生成get方法,只读,默认为readwrite@property (retain) NSObject *obj1; // set方法中进行指针的更改(release旧值,retain新值,一般用于对象,关于内存管理后面会涉及)@property (copy) NSString *name3; // set方法中进行指针的更改(release旧值),并创建新的对象(一般用于字符串)@property (nonatomic) NSObject *obj2; // 在多线程设计时,通过atomic(默认)创建对象,保证多个程序不能同时set属性,这浪费资源,在手机端一般不会多线程访问,一般都加nonatomic@property (getter = getName, nonatomic, copy) NSObject *obj3; // 可以同时设置多个属性

4、为什么要封装?
我们这么麻烦的将属性进行封装,这样有什么意义?
① 通过set方法来设置属性,我们可以通过代码对属性进行定制和过滤分析,灵活;
② 外部不直接通过属性的名称来访问属性,方便了程序的后期更改,我们只要保证方法不变,内部的参数我们可以随意改动;
③ 安全,外部不能得到属性的地址,不会因为指针操作的问题导致程序崩溃,而且外部很难窥探我的技术实现细节;



-----------Java培训、Android培训、IOS培训、.Net培训、期待与您交流!------------ 
0 0
原创粉丝点击