在
iOS
的面试中经常会被问到如何为分类添加属性,但是鲜少听人提过协议中添加属性的情况。
我们知道协议是一组特定功能或者行为的规范,这个概念和C#
或者Java
中的接口是一样的,但是C#
或者Java
中的接口类中都可以定义属性的,那么在OC
的协议中定义属性可不可以呢
很简单你试一下就知道是可以的,但网上查阅很多资料的时候你会发现很多地方根本没有提起过协议中定义属性,甚至有直接说协议中不能定义属性的。
我们来试一下:
未实现警告
当我们在协议中定义一个必须实现(@ required
修饰)的属性以后,如果实现类没有对这个属性做任何实现那么XCode
中实现类中就会发出警告
方式一:在.m实现类中添加@synthesize speed;
@protocol FlyDelegate <NSObject>
@required
@property(nonatomic, assign) NSUInteger speed;
@end
@interface TestProtocolProperty : NSObject<FlyDelegate>
@end
@implementation TestProtocolProperty
@synthesize speed;
- (instancetype)init {
if (self = [super init]) {
}
return self;
}
@end
方式二:在.m实现文件中添加合成
speed
属性的成员变量_speed
和对应的getter
和setter
方法
@protocol FlyDelegate <NSObject>
@required
@property(nonatomic, assign) NSUInteger speed;
@end
@interface TestProtocolProperty : NSObject<FlyDelegate> {
NSUInteger _speed;
}
@end
@implementation TestProtocolProperty
- (instancetype)init {
if (self = [super init]) {
}
return self;
}
- (void)setSpeed:(NSUInteger)speed {
_speed = speed;
}
- (NSUInteger)speed {
return _speed;
}
@end
其实iOS的UIKit
中就有协议中声明属性的例子:
打开UIKit
中的协议UIApplicationDelegate
声明就可以看到属性window;
- (void)applicationDidEnterBackground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);
- (void)applicationWillEnterForeground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);
- (void)applicationProtectedDataWillBecomeUnavailable:(UIApplication *)application NS_AVAILABLE_IOS(4_0);
- (void)applicationProtectedDataDidBecomeAvailable:(UIApplication *)application NS_AVAILABLE_IOS(4_0);
@property (nullable, nonatomic, strong) UIWindow *window NS_AVAILABLE_IOS(5_0);
结论:
OC
语言的协议里面是支持声明属性的,而在协议中声明属性其实和在其中定义方法一样只是声明了getter
和setter
方法,并没有具体实现,所以当这个协议属性修饰符为@ required
时,如果不实现编译器就会报出警告,最简单的方式就是加上属性同步语句@synthesize propertyName;
思考:属性和方法其实都是一个事物的特性,协议正是描述某类行为和特性的一种规范,基于这个事实,所以在协议中定义属性是很符合道理的。之所以在iOS
开发中很少看到有人这么使用过是因为,iOS
开发中协议通常是被用作代理模式而存在的,并且如果在协议中定义了是属性,就必须在实现类中添加对属性自动同步或者手动添加属性实现代码
(本文中讨论的协议中属性这个话题本身是没什么技术深度,但是却可以打开思维的广度)