我见过Objective-C协议的使用,如下所示:
@protocol MyProtocol <NSObject>
@required
@property (readonly) NSString *title;
@optional
- (void) someMethod;
@end
我见过使用这种格式,而不是编写一个子类扩展的具体超类。问题是,如果你遵循这个协议,你需要自己合成属性吗?如果你正在扩展一个超类,答案显然是否定的,你不需要这样做。但是,如何处理协议要求遵守的属性呢?
据我所知,您仍然需要在符合需要这些属性的协议的对象的头文件中声明实例变量。在这种情况下,我们可以假设它们只是一个指导原则吗?对于需要的方法,CLearly并非如此。编译器会因为排除了协议列出的所需方法而责备你。然而,属性背后的故事是什么呢?
下面是一个生成编译错误的示例(注意:我已经修剪了代码,它没有反映当前的问题):
MyProtocol.h
@protocol MyProtocol <NSObject>
@required
@property (nonatomic, retain) id anObject;
@optional
TestProtocolsViewController.h
- (void)iDoCoolStuff;
@end
#import <MyProtocol.h>
@interface TestProtocolsViewController : UIViewController <MyProtocol> {
}
@end
TestProtocolsViewController.m
#import "TestProtocolsViewController.h"
@implementation TestProtocolsViewController
@synthesize anObject; // anObject doesn't exist, even though we conform to MyProtocol.
- (void)dealloc {
[anObject release]; //anObject doesn't exist, even though we conform to MyProtocol.
[super dealloc];
}
@end
发布于 2009-05-10 05:46:00
该协议只是告诉通过该协议了解您的类的每个人,属性anObject
将在那里。协议不是真实的,它们本身没有变量或方法-它们只描述了一组关于您的类的特定属性,以便持有对它们的引用的对象可以以特定的方式使用它们。
这意味着在符合协议的类中,您必须尽一切努力确保anObject正常工作。
@property
和@synthesize
本质上是为您生成代码的两种机制。@property
只是说该属性名称将有一个getter (和/或setter)方法。如今,仅靠@property
就足以让系统为您创建方法和存储变量(您过去必须添加@sythesize
)。但是你必须有一些东西来访问和存储变量。
发布于 2011-01-02 22:35:59
这是我的一个完美工作的例子,首先是协议定义:
@class ExampleClass;
@protocol ExampleProtocol
@required
// Properties
@property (nonatomic, retain) ExampleClass *item;
@end
下面是一个支持该协议的类的工作示例:
#import <UIKit/UIKit.h>
#import "Protocols.h"
@class ExampleClass;
@interface MyObject : NSObject <ExampleProtocol> {
// Property backing store
ExampleClass *item;
}
@implementation MyObject
// Synthesize properties
@synthesize item;
@end
发布于 2014-05-08 06:04:36
示例:2个类(Person和Serial)要使用Viewer的服务...并且必须符合ViewerProtocol。viewerTypeOfDescription是订阅服务器类必须符合的强制属性。
typedef enum ViewerTypeOfDescription {
ViewerDataType_NSString,
ViewerDataType_NSNumber,
} ViewerTypeOfDescription;
@protocol ViewerProtocol
@property ViewerTypeOfDescription viewerTypeOfDescription;
- (id)initConforming;
- (NSString*)nameOfClass;
- (id)dataRepresentation;
@end
@interface Viewer : NSObject
+ (void) printLargeDescription:(id <ViewerProtocol>)object;
@end
@implementation Viewer
+ (void) printLargeDescription:(id <ViewerProtocol>)object {
NSString *data;
NSString *type;
switch ([object viewerTypeOfDescription]) {
case ViewerDataType_NSString: {
data=[object dataRepresentation];
type=@"String";
break;
}
case ViewerDataType_NSNumber: {
data=[(NSNumber*)[object dataRepresentation] stringValue];
type=@"Number";
break;
}
default: {
data=@"";
type=@"Undefined";
break;
}
}
printf("%s [%s(%s)]\n",[data cStringUsingEncoding:NSUTF8StringEncoding],
[[object nameOfClass] cStringUsingEncoding:NSUTF8StringEncoding],
[type cStringUsingEncoding:NSUTF8StringEncoding]);
}
@end
/* A Class Person */
@interface Person : NSObject <ViewerProtocol>
@property NSString *firstname;
@property NSString *lastname;
@end
@implementation Person
// >>
@synthesize viewerTypeOfDescription;
// <<
@synthesize firstname;
@synthesize lastname;
// >>
- (id)initConforming {
if (self=[super init]) {
viewerTypeOfDescription=ViewerDataType_NSString;
}
return self;
}
- (NSString*)nameOfClass {
return [self className];
}
- (NSString*) dataRepresentation {
if (firstname!=nil && lastname!=nil) {
return [NSString stringWithFormat:@"%@ %@", firstname, lastname];
} else if (firstname!=nil) {
return [NSString stringWithFormat:@"%@", firstname];
}
return [NSString stringWithFormat:@"%@", lastname];
}
// <<
@end
/* A Class Serial */
@interface Serial : NSObject <ViewerProtocol>
@property NSInteger amount;
@property NSInteger factor;
@end
@implementation Serial
// >>
@synthesize viewerTypeOfDescription;
// <<
@synthesize amount;
@synthesize factor;
// >>
- (id)initConforming {
if (self=[super init]) {
amount=0; factor=0;
viewerTypeOfDescription=ViewerDataType_NSNumber;
}
return self;
}
- (NSString*)nameOfClass {
return [self className];
}
- (NSNumber*) dataRepresentation {
if (factor==0) {
return [NSNumber numberWithInteger:amount];
} else if (amount==0) {
return [NSNumber numberWithInteger:0];
}
return [NSNumber numberWithInteger:(factor*amount)];
}
// <<
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
Person *duncan=[[Person alloc]initConforming];
duncan.firstname=@"Duncan";
duncan.lastname=@"Smith";
[Viewer printLargeDescription:duncan];
Serial *x890tyu=[[Serial alloc]initConforming];
x890tyu.amount=1564;
[Viewer printLargeDescription:x890tyu];
NSObject *anobject=[[NSObject alloc]init];
//[Viewer printLargeDescription:anobject];
//<< compilator claim an issue the object does not conform to protocol
}
return 0;
}
通过subClassing进行协议继承的另一个示例
typedef enum {
LogerDataType_null,
LogerDataType_int,
LogerDataType_string,
} LogerDataType;
@protocol LogerProtocol
@property size_t numberOfDataItems;
@property LogerDataType dataType;
@property void** data;
@end
@interface Loger : NSObject
+ (void) print:(id<LogerProtocol>)object;
@end
@implementation Loger
+ (void) print:(id<LogerProtocol>)object {
if ([object numberOfDataItems]==0) return;
void **data=[object data];
for (size_t i=0; i<[object numberOfDataItems]; i++) {
switch ([object dataType]) {
case LogerDataType_int: {
printf("%d\n",(int)data[i]);
break;
}
case LogerDataType_string: {
printf("%s\n",(char*)data[i]);
break;
}
default:
break;
}
}
}
@end
// A Master Class
@interface ArrayOfItems : NSObject <LogerProtocol>
@end
@implementation ArrayOfItems
@synthesize dataType;
@synthesize numberOfDataItems;
@synthesize data;
- (id)init {
if (self=[super init]) {
dataType=LogerDataType_null;
numberOfDataItems=0;
}
return self;
}
@end
// A SubClass
@interface ArrayOfInts : ArrayOfItems
@end
@implementation ArrayOfInts
- (id)init {
if (self=[super init]) {
self.dataType=LogerDataType_int;
}
return self;
}
@end
// An other SubClass
@interface ArrayOfStrings : ArrayOfItems
@end
@implementation ArrayOfStrings
- (id)init {
if (self=[super init]) {
self.dataType=LogerDataType_string;
}
return self;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
ArrayOfInts *arr=[[ArrayOfInts alloc]init];
arr.data=(void*[]){(int*)14,(int*)25,(int*)74};
arr.numberOfDataItems=3;
[Loger print:arr];
ArrayOfStrings *arrstr=[[ArrayOfStrings alloc]init];
arrstr.data=(void*[]){(char*)"string1",(char*)"string2"};
arrstr.numberOfDataItems=2;
[Loger print:arrstr];
}
return 0;
}
https://stackoverflow.com/questions/844678
复制相似问题