在
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
開發中協議通常是被用作代理模式而存在的,并且如果在協議中定義了是屬性,就必須在實現類中添加對屬性自動同步或者手動添加屬性實現代碼
(本文中討論的協議中屬性這個話題本身是沒什么技術深度,但是卻可以打開思維的廣度)