简体   繁体   English

在类中使用self方法

[英]Using self in class method

I came across this code in ShareKit, and I don't understand what the writer had in mind, using self in a class method. 我在ShareKit中遇到了这个代码,我不明白作者的想法,在类方法中使用self There is a warning: Incompatible pointer types sending 'Class' to parameter type id<FBSessionDelegate> . 有一个警告:不兼容的指针类型将'Class'发送到参数类型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? 我能做什么/应该做什么不会打破这个?

This is is the file SHKFacebook.m and the class name is SHKFacebook 这是SHKFacebook.m文件,类名是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 may be used in a class method as a polymorphic Class instance. self可以在类方法中用作多态类实例。

therefore, the class method new can be implemented like this: 因此,类方法new可以像这样实现:

+ (id)new
{
  return [[self alloc] init];
}

and would return the correct type for the Class instance that is messaged: 并将为消息的Class实例返回正确的类型:

ex a: 前:

NSArray * a = [NSArray new]; // << a is an NSArray

ex b: ex b:

NSMutableArray * a = [NSMutableArray new]; // << a is an NSMutableArray

see note below. 见下面的注释。

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. 所以你真正面临的是确保协议中只有实例方法,并且(Class)self的方法映射出来采用协议中的实例方法。

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. 单身人士会更清楚,更正确,但我甚至不喜欢单身人士,所以我不会采取这种方式。

The warning is produced because the Class instance (what is passed) does adopt the @protocol specified by the delegate parameter. 产生警告是因为Class实例(传递的内容)确实采用了delegate参数指定的@protocol The Class instance is not an instance of the class. Class实例不是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? 例如,如果采用NSLocking ,编译器是否希望您还为协议中声明的每个实例方法实现类方法? 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. 您正在处理的实现是IMO其中一种滥用语言的情况,但它恰好起作用。

To clarify the terminology: 澄清术语:

The " Class instance" is self in a class method: Class实例”在类方法中是self

+ (void)foo { self; }

An "instance of the class" is self in an instance method: “类的实例”在实例方法中是self

- (void)foo { self; }

In practice, -[NSObject conformsToProtocol:] is +[NSObject conformsToProtocol:] and +[NSObject class] just returns self so there are no errors at execution. 实际上, -[NSObject conformsToProtocol:]+[NSObject conformsToProtocol:]+[NSObject class]只返回self因此执行时没有错误。

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. 我描述的标准适用于执行 ,但它偏离了语言的语义 - 因此,编译器绝对正确。

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 . 解决问题:没有办法告诉编译器“我的类实例符合协议 ”,因为采用声明适用于类的实例

You have two primary options: 您有两个主要选择:

  1. The clean, correct approach: Use an instance of the class and implement the protocol as defined. 干净,正确的方法:使用类的实例并实现定义的协议。

  2. or Typecast the class instance to the protocol: 或Typecast协议的类实例:

    id delegate = (id)self; id delegate =(id)self; fbSession = [FBSession sessionForApplication:SHKFacebookKey getSessionProxy:SHKFacebookSessionProxyURL delegate:delegate]; fbSession = [FBSession sessionForApplication:SHKFacebookKey getSessionProxy:SHKFacebookSessionProxyURL delegate:delegate];

If you choose #2, it may help to define the instance methods of the protocol to use class methods, like so: 如果选择#2,则可以帮助定义协议的实例方法以使用类方法,如下所示:

+ (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];
}

then you can just write: 然后你可以写:

fbSession = [FBSession sessionForApplication:SHKFacebookKey
                             getSessionProxy:SHKFacebookSessionProxyURL
                                    delegate:[self sharedSomeProtocolDelegate]];

(note that the implementations of these types are actually class clusters, and you will see something different in the debugger or if printed) (请注意,这些类型的实现实际上是类集群,您将在调试器中看到不同的内容或打印出来的内容)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM