您好,欢迎访问代码之道!登录后台查看权限
  • 欢迎大神光临
  • 有朋自远方来 不亦悦乎

Objective-C教程之属性

ObjC教程 老刘 2018-08-09 756 次浏览 0个评论

封装

在面向对象设计中,一般不会直接暴露类成员变量给外部使用,一个对外的成员变量往往是通过一个方法控制赋值(setter), 通过一个方法提供访问接口(getter)。语法规定setter方法只有一个参数且以set开头,getter方法没有参数,返回对应的类型, 按照这种语法的方法支持用.调用。

#include <Foundation/Foundation.h>

@interface MSPerson : NSObject
- (int)age;
- (NSString *)name;

- (void)setAge:(int)age;
- (void)setName:(NSString *)name;

@end

@implementation  MSPerson {
    int age_;
    NSString *name_;
}

- (int)age {
    return age_;
}

- (NSString *)name {
    return name_;
}

- (void)setAge:(int)age {
    age_ = age;
}

- (void)setName:(NSString *)name {
    name_ = [name copy];
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MSPerson *p1 = [[MSPerson alloc] init];
        p1.name = @"jack";
        // 等价于
        // [p1 setName:@"jack"];
        p1.age = 18;
        // 等价于
        // [p1 setAge:18];
        NSLog(@"%@:age=%d", p1.name/*等价于[p1 name]*/, p1.age/*等价于[p1 age]*/);
    }

    return 0;
}

/*
 程序输出:
 2018-08-09 17:17:56.944 属性[4306:78694] jack:age=18
*/

属性

setter和getter方法是如此有规律,因此Objective-C提供专门的简化语言特性属性属性是一种语法糖而已,让编译器自动生成getter和setter方法。

添加一个属性分为两个步骤,第一,在接口中使用@property关键字声明属性的类型和名称,格式如下

@property 属性类型 属性名称;

第二,在类实现中使用@synthesize关键字指定属性对应的是那个成员变量,格式如下

@synthesize 属性名称 = 成员变量名称;

下面还是看个例子,让我们体验一下属性的使用方法。

#include <Foundation/Foundation.h>

@interface MSPerson : NSObject
- (int)_age;
- (NSString *)_name;

- (void)_age:(int)_age;
- (void)_name:(NSString *)_name;

@property int age;
@property NSString *name;

@end

@implementation  MSPerson {
    int age_;
    NSString *name_;
}

@synthesize age = age_;
@synthesize name = name_;

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MSPerson *p1 = [[MSPerson alloc] init];
        p1.name = @"jack";
        // 等价于
        // [p1 setName:@"jack"];
        p1.age = 18;
        // 等价于
        // [p1 setAge:18];
        NSLog(@"%@:age=%d", p1.name/*等价于[p1 name]*/, p1.age/*等价于[p1 age]*/);
    }

    return 0;
}

/*
 程序输出:
 2018-08-09 17:17:56.944 属性[4306:78694] jack:age=18
*/

属性简化

可以不声明也不指定成员变量,这样默认会生成_开头的成员变量,比如下面例子会生成int _age;和'NSString *_name'成员变量, 在类内,可以直接通过变量名称访问他们。

#include <Foundation/Foundation.h>

@interface MSPerson : NSObject

@property int age;
@property NSString *name;

@end

@implementation  MSPerson
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MSPerson *p1 = [[MSPerson alloc] init];
        p1.name = @"jack";
        // 等价于
        // [p1 setName:@"jack"];
        p1.age = 18;
        // 等价于
        // [p1 setAge:18];
        NSLog(@"%@:age=%d", p1.name/*等价于[p1 name]*/, p1.age/*等价于[p1 age]*/);
    }

    return 0;
}

/*
 程序输出:
 2018-08-09 17:17:56.944 属性[4306:78694] jack:age=18
*/

属性描述(specifiers)

可以在@property和类型之间添加(),在里面对属性进行进一步描述,描述符(nonatomic或者atomic, readwrite或者readonly,strong或者weak) 可以有多个,用,隔开。

添加有描述符的属性声明格式如下

@property (描述符1,描述符符2...描述符n) 属性类型 属性名称;

下面还是看个例子,让我们的思路更加清晰。

#include <Foundation/Foundation.h>

@interface MSPerson : NSObject

@property (nonatomic, assign)int age;
@property (nonatomic, copy) NSString *name;

@end

@implementation  MSPerson
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MSPerson *p1 = [[MSPerson alloc] init];
        p1.name = @"jack";
        // 等价于
        // [p1 setName:@"jack"];
        p1.age = 18;
        // 等价于
        // [p1 setAge:18];
        NSLog(@"%@:age=%d", p1.name/*等价于[p1 name]*/, p1.age/*等价于[p1 age]*/);
    }

    return 0;
}

/*
 程序输出:
 2018-08-09 17:17:56.944 属性[4306:78694] jack:age=18
*/

已有 756 位网友参与,快来吐槽:

发表评论