使用自我课堂方法 [英] Using self in class method
问题描述
我在ShareKit中遇到了这段代码,但我不理解作者在类方法中使用 self
的想法。有一个警告:不兼容的指针类型会将 Class发送到参数类型 id< FBSessionDelegate>
。 我想清除这些警告,以便以后可以看到可能会造成伤害的警告。我能/应该做些什么不会破坏这个?
I came across this code in ShareKit, and I don't understand what the writer had in mind, using self
in a class method. There is a warning: Incompatible pointer types sending 'Class' to parameter type id<FBSessionDelegate>
. I want to clean up these warnings, so I can see the ones that may hurt later. What can/should I do that won't break this?
这是文件SHKFacebook.m,类名是SHKFacebook
This is is the file SHKFacebook.m and the class name is SHKFacebook
+ (void)logout
{
FBSession *fbSession;
if(!SHKFacebookUseSessionProxy){
fbSession = [FBSession sessionForApplication:SHKFacebookKey
secret:SHKFacebookSecret
delegate:self];
}else {
fbSession = [FBSession sessionForApplication:SHKFacebookKey
getSessionProxy:SHKFacebookSessionProxyURL
delegate:self];
}
[fbSession logout];
}
推荐答案
self
可以在类方法中用作多态Class实例。
self
may be used in a class method as a polymorphic Class instance.
因此,类方法 new
可以这样实现:
therefore, the class method new
can be implemented like this:
+ (id)new
{
return [[self alloc] init];
}
并会为所发送的Class实例返回正确的类型:
and would return the correct type for the Class instance that is messaged:
ex a:
NSArray * a = [NSArray new]; // << a is an NSArray
ex b:
NSMutableArray * a = [NSMutableArray new]; // << a is an NSMutableArray
请参见以下说明。
所以您真正要面对的是确保协议中只有实例方法,并且(类)self的方法可以映射为在协议中采用实例方法。
So what you are really faced with is ensuring there are only instance methods in the protocol, and that (Class) self's methods map out to adopt the instance methods in the protocol.
就设计而言……好吧,让我们说我不会这样写。单身人士本来会更清楚,更正确,但我什至不喜欢单身人士,因此我不会走那条路线。
As far as the design... well, let's just say I would not have written it this way. A singleton would have been clearer and more correct, but I don't even like singletons so I would not have taken that route.
产生警告是因为 Class 实例(传递的实例)确实采用了 delegate
参数指定的 @protocol
。 Class
实例不是该类的实例。协议声明确实适用于该类的 instances 。例如,如果您采用 NSLocking
,编译器是否希望您也为协议中声明的每个实例方法实现类方法?答:从不。您正在处理的实现是IMO之一,在这种情况下它会滥用该语言,但它确实起作用。
The warning is produced because the Class instance (what is passed) does adopt the @protocol
specified by the delegate
parameter. The Class
instance is not an instance of the class. A protocol declaration really applies to instances of the class. For example, if you adopt NSLocking
, does the compiler expect you to also implement class methods for every instance method declared in the protocol? Answer: Never. The implementation you're dealing with is IMO one of those cases where it's a misuse of the language, but it happens to work.
要澄清术语,
Class
实例是 self
在类方法中:
The "Class
instance" is self
in a class method:
+ (void)foo { self; }
阶级的实例是自己
在实例方法中:
An "instance of the class" is self
in an instance method:
- (void)foo { self; }
在实践中,-[NSObjectconformsToProtocol:]
是 + [NSObjectconformsToProtocol:]
和 + [NSObject class]
仅返回 self
所以执行时没有错误。
In practice, -[NSObject conformsToProtocol:]
is +[NSObject conformsToProtocol:]
and +[NSObject class]
just returns self
so there are no errors at execution.
我仍然不清楚,为什么我会收到如果代码符合您描述的条件,则会发出警告。
I'm still not clear, then, why I am receiving a warning, if the code meets the criteria you described.
我描述的条件适用于执行 ,但它偏离了语言的语义-因此,编译器对此是绝对正确的。
The criteria I described applies to the execution, but it deviates from the semantics of the language -- thus, the compiler is absolutely correct on this.
要解决该问题:无法告诉编译器我的Class实例符合 protocol ,因为采用声明适用于该类的实例。
For a resolution to the problem: There's no way to tell the compiler "My Class instance conforms to protocol" because declaration of adoption applies to instances of the class.
您有两个主要选项:
-
干净,正确的方法:使用该类的实例并按定义实现协议。
The clean, correct approach: Use an instance of the class and implement the protocol as defined.
或将类实例转换为协议类型:
or Typecast the class instance to the protocol:
id代表=(id)自我;
fbSession = [FBSession sessionForApplication:SHKFacebookKey
getSessionProxy:SHKFacebookSessionProxyURL
委托人:代表];
id delegate = (id)self; fbSession = [FBSession sessionForApplication:SHKFacebookKey getSessionProxy:SHKFacebookSessionProxyURL delegate:delegate];
如果选择#2,则可能有助于定义协议的实例方法以使用类方法,例如:
If you choose #2, it may help to define the instance methods of the protocol to use class methods, like so:
+ (void)protocolMethod { /* do stuff */ }
- (void)protocolMethod { [self.class protocolMethod]; }
这也意味着您永远不需要实例。这将有所帮助,因为如果协议将更改,它将添加警告。遵循约定时,这些警告会冒泡到类方法上。
that would also imply you never need instances. It would help because it will add warnings if the protocol will change. These warnings would bubble up to class methods when you follow the convention.
为减少噪音,您还可以考虑创建一些方法以将类型转换减少到一个位置:
To reduce noise, you may also consider creating some method to reduce the typecast to one location:
+ (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return (id<SomeProtocol>)self;
}
- (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return [[self class] sharedSomeProtocolDelegate];
}
然后您可以这样写:
fbSession = [FBSession sessionForApplication:SHKFacebookKey
getSessionProxy:SHKFacebookSessionProxyURL
delegate:[self sharedSomeProtocolDelegate]];
(请注意,这些类型的实现实际上是类集群,您会看到一些
这篇关于使用自我课堂方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!