self
可以在类方法中用作多态类实例。
因此,类方法new
可以这样实现:
+ (id)new
{
return [[self alloc] init];
}
并将返回消息传递的 Class 实例的正确类型:
例如:
NSArray * a = [NSArray new]; // << a is an NSArray
例如:
NSMutableArray * a = [NSMutableArray new]; // << a is an NSMutableArray
请参阅下面的注释。
所以你真正面临的是确保协议中只有实例方法,并且(类)自身的方法映射出来采用协议中的实例方法。
至于设计......好吧,让我们说我不会这样写。单身人士会更清晰,更正确,但我什至不喜欢单身人士,所以我不会走那条路。
产生警告是因为Class实例(传递的内容)确实采用了参数@protocol
指定的值delegate
。该Class
实例不是该类的实例。协议声明确实适用于类的实例。例如,如果您采用NSLocking
,编译器是否希望您也为协议中声明的每个实例方法实现类方法?答:从来没有。您正在处理的实现是 IMO 滥用该语言的情况之一,但它恰好可以工作。
为了澄清术语:
“Class
实例”self
在类方法中:
+ (void)foo { self; }
“类的实例”self
在实例方法中:
- (void)foo { self; }
在实践中,-[NSObject conformsToProtocol:]
is+[NSObject conformsToProtocol:]
并且+[NSObject class]
只是返回self
,因此执行时没有错误。
那么,如果代码符合您描述的标准,我仍然不清楚为什么我会收到警告。
我描述的标准适用于执行,但它偏离了语言的语义——因此,编译器在这方面是绝对正确的。
为了解决这个问题:没有办法告诉编译器“我的类实例符合协议”,因为采用声明适用于类的实例。
您有两个主要选择:
干净、正确的方法:使用类的实例并按照定义实现协议。
或将类实例类型转换为协议:
id 委托 = (id)self; fbSession = [FBSession sessionForApplication:SHKFacebookKey getSessionProxy:SHKFacebookSessionProxyURL delegate:delegate];
如果您选择#2,它可能有助于定义协议的实例方法以使用类方法,如下所示:
+ (void)protocolMethod { /* do stuff */ }
- (void)protocolMethod { [self.class protocolMethod]; }
这也意味着您永远不需要实例。这会有所帮助,因为如果协议发生更改,它将添加警告。当您遵循约定时,这些警告会冒泡到类方法。
为了减少噪音,您还可以考虑创建一些方法来将类型转换减少到一个位置:
+ (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return (id<SomeProtocol>)self;
}
- (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return [[self class] sharedSomeProtocolDelegate];
}
然后你可以写:
fbSession = [FBSession sessionForApplication:SHKFacebookKey
getSessionProxy:SHKFacebookSessionProxyURL
delegate:[self sharedSomeProtocolDelegate]];
(注意这些类型的实现实际上是类簇,你会在调试器中看到不同的东西,或者如果打印出来)