一些详细知识

@property和@protocol小记

2016-03-13  本文已影响1285人  风往北吹_

众所周知,@property是Objective-C语言的关键字,在xcode4.5之前的版本需要与@synthesize配对使用,之后则可以单独使用。作用是通过合成存取方法来封装对象中的数据,通常被称为属性。因此,@property 的本质就是ivar(实例变量) 和 getter/setter(存取方法)。编译器是根据Objective-C严格的命名规范来生成存取方法的,因此实例变量前面会加下划线(_),gettter方法就是属性名,setter方法就是在属性名前面加set。

下面并不打算讨论@property的细节问题,而是着重说明一下@property在遇到@protocol时的一些小的变化。对于@protocol,在iOS开发中见得最多的应该是把它用于代理,例如:

UITableView的代理
UITableViewDelegate,UITableViewdataSource,
UIScrollView的代理
UIScrollViewDelegate等等。

而@protocol最重要的还应该用于作为接口(或者叫抽象基类)。由于Objective-C语言不存在多重继承一说,因此抽象基类很少这样叫。常被提及的应该是面向协议编程。

关于@protocol的简单使用:


// Parent.h
@protocol Parent <NSObject>
- (void)setName:(NSString *)name;
- (NSString *)name;
@end

// Child.h
@interface Child : NSObject<Parent>{
    NSString *name_;
}

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

@end

// Child.m
@implementation Child

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

- (NSString *)name {
    return name_;
}
@end

以上示例,定义协议Parent,Child遵从这个协议就必须由自己去实现,这是理所应当的事情。如果不去实现:

警告信息:Method 'setName:' in protocol 'Parent' not implemented
Method 'name:' in protocol 'Parent' not implemented

意思是:Parent协议中的方法setName和name没有实现

假如

协议Parent中使用@property呢?协议中明确说明不能声明成员变量,@property并不是,应该说并不仅仅是。代码如下:

// Parent.h
@protocol Parent <NSObject>
@property (copy, nonatomic) NSString *name;
@end

// Child.h
@interface Child : NSObject<Parent>
// 假如这里面什么也不写 
//@property (copy, nonatomic) NSString *name;

// 假如这里面这样写是否正确?
- (void)setName:(NSString *)name;
- (NSString *)name;

@end

// Child.m
@implementation Child

@end

答案是:两种写法都可以,不过什么也不写编译器一定会发出警告,这是毋庸置疑的。只是,警告与上面有所不同。

警告信息:Auto property synthesis will not synthesize property 'name' declared in protocol 'Parent'
意思是:Parent协议中的属性name不会被自动合成,也就是不会自动合成存取方法和实例变量。

再次假如

协议Parent中使用setName和name,Child遵从Parent协议,但是使用@property来合成setName和name方法,同样可行。

因此,结论是@property是可以在@protocol中使用的,只是由于@protocol特性的限制,@property在@protocol中并不会合成实例变量,只会合成存取方法。因此在@protocol中使用了@property,对应的在遵从此协议的类中,如果不需要重写setter和getter的情况写也使用@property交给编译器自动合成。

注意:@property合成的实例变量只有自己可以直接访问,也就是(_XX = ?),如果还有子类继承Child,则只能通过点语法访问,或者直接调用setter和getter方法访问。

最后针对Objective-C协议补充说明

1)Protocol:就一个用途,用来声明一大堆的方法(不能声明成员变量),不能写实现

2)只要某个类遵守了这个协议,就拥有了这个协议中的所有方法声明

3)只要父类遵守了某个协议,那么子类也遵守

4)Protocol声明的方法可以让任何类去实现,protocol就是协议

5)OC不能继承多个类(多继承)但是能够遵守多个协议,继承(:),遵守协议(<>)

6)基协议:<NSObject>基协议,是最根本最基本的协议,其中声明了很多最基本的方法

7)协议可以遵守协议,一个协议遵守了另一个协议,就可以拥有另一个协议中的方法声明(称为协议继承)

上一篇下一篇

猜你喜欢

热点阅读