2012-01-27 119 views
8

我在ShareKit中遇到過這樣的代碼,我不明白作者的想法,在類方法中使用self。有一個警告:不兼容的指針類型將'Class'發送到參數類型id<FBSessionDelegate>我想清理這些警告,所以我可以看到那些稍後可能會受傷的警告。我可以/應該做什麼,不會破壞這個?在課堂教學中使用自我

這是是文件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]; 
} 

回答

13

self可以在一個類的方法作爲多晶型類實例中使用。

因此,類方法new可以實現這樣的:

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

和將返回正確的類型對於被傳遞消息類實例:

前一個:

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

ex b:

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

請參閱下面的註釋。

所以你真正要面對的是確保協議中只有實例方法,並且(類)自己的方法映射出採用協議中的實例方法。

就設計......好吧,我們只是說我不會這樣寫的。一個單身人士會更清楚,更正確,但我甚至不喜歡單身人士,所以我不會採取這樣的路線。

產生此警告是因爲類別實例(通過的內容)確實採用delegate參數指定的@protocolClass實例不是該類的一個實例。協議聲明確實適用於該類的實例。例如,如果採用NSLocking,編譯器是否希望您也爲協議中聲明的每個實例方法實現類方法?答:從來沒有。你正在處理的實施是國際海事組織是這種語言濫用的情況之一,但它恰好運作。

爲了闡明術語:

的 「Class實例」 是self在一個類的方法:

+ (void)foo { self; } 

的 「類的實例」 是在實例方法self

- (void)foo { self; } 

實際上,-[NSObject conformsToProtocol:]+[NSObject conformsToProtocol:]+[NSObject class]只是返回self所以執行時沒有錯誤。

我還不清楚,那麼,爲什麼我收到警告,如果代碼符合您描述的標準。

我描述的標準適用於執行,但它從語言的語義偏離 - 因此,編譯器對這個絕對正確的。

對於解決的問題:有沒有辦法告訴編譯器「我的類的實例符合協議」,因爲採用的聲明適用於類的實例。

你有兩個主要選擇:

  1. 乾淨的,正確的做法:使用類的一個實例和實施所定義的協議。

  2. 或類型轉換類實例的協議:

    ID代表=(ID)自我; 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]]; 

(注意的實現這些類型實際上是類集羣,並且您將在調試器中看到不同的東西或者如果打印出來)

+0

您的編輯已清除。順便說一句,該協議只包含實例方法,它們都不涉及接收方。我仍然不清楚,那麼,爲什麼我收到警告,如果代碼符合您描述的標準。 – Jim 2012-01-27 04:01:50

+0

@Jim詳細添加 – justin 2012-01-27 06:21:14