2012-01-27 36 views
8

Tôi đã xem đoạn mã này trong phần ShareKit, và tôi không hiểu ý tưởng của nhà văn khi sử dụng self trong một phương thức lớp học. Có một cảnh báo: Các kiểu con trỏ không tương thích gửi 'Lớp' tới kiểu tham số id<FBSessionDelegate>. Tôi muốn làm sạch những cảnh báo này, vì vậy tôi có thể thấy những cảnh báo có thể bị tổn thương sau này. Tôi có thể làm gì/tôi nên làm điều đó sẽ không phá vỡ điều này?Sử dụng phương pháp tự học theo lớp

Đây là là file SHKFacebook.m và tên lớp là 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]; 
} 

Trả lời

13

self có thể được sử dụng trong một phương pháp học như một ví dụ lớp đa hình.

do đó, phương pháp lớp new thể được thực hiện như thế này:

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

và sẽ trả lại đúng loại cho các ví dụ lớp được nhắn tin cho:

cũ a:

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

ex b:

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

xem ghi chú bên dưới. Vì vậy, những gì bạn đang thực sự phải đối mặt với là đảm bảo chỉ có các phương thức cá thể trong giao thức, và các phương thức tự (lớp) của nó ánh xạ để áp dụng các phương thức cá thể trong giao thức.

Theo như thiết kế ... tốt, chúng ta hãy nói rằng tôi sẽ không viết nó theo cách này. Một singleton sẽ rõ ràng hơn và chính xác hơn, nhưng tôi thậm chí không thích những người độc thân nên tôi sẽ không đi theo con đường đó.

Cảnh báo được sản xuất bởi vì Lớp dụ (những gì được truyền) không áp dụng @protocol định bởi tham số delegate. Ví dụ Class không phải là một thể hiện của lớp. Tuyên bố giao thức thực sự áp dụng cho trường hợp của lớp học. Ví dụ: nếu bạn áp dụng NSLocking, trình biên dịch có mong đợi bạn cũng triển khai các phương thức lớp cho mọi phương thức mẫu được khai báo trong giao thức không? Trả lời: Không bao giờ. Việc thực hiện bạn đang đối phó với IMO là một trong những trường hợp mà nó là một lạm dụng ngôn ngữ, nhưng nó sẽ xảy ra để làm việc.

Để làm rõ các thuật ngữ:

Các "Class dụ" là self trong một phương pháp học:

+ (void)foo { self; } 

An "thể hiện của lớp" là self trong một phương pháp dụ:

- (void)foo { self; } 

Trong thực tế, -[NSObject conformsToProtocol:]+[NSObject conformsToProtocol:]+[NSObject class] chỉ trả lại self do đó không có lỗi khi thực thi.

Tôi vẫn chưa rõ, tại sao tôi nhận được cảnh báo, nếu mã đáp ứng tiêu chí bạn mô tả.

Các tiêu chí tôi đã mô tả áp dụng cho thực hiện, nhưng nó lệch khỏi ngữ nghĩa của ngôn ngữ - do đó, trình biên dịch là hoàn toàn chính xác về vấn đề này.

Đối với một giải pháp cho vấn đề này: Không có cách nào để nói với trình biên dịch "dụ lớp của tôi phù hợp với giao thức " vì tuyên bố thông qua áp dụng cho thể hiện của lớp.

Bạn có hai lựa chọn chính:

  1. Các sạch, cách tiếp cận đúng: Sử dụng một thể hiện của lớp và thực hiện các giao thức theo quy định.

  2. hoặc định kiểu cá thể lớp giao thức:

    id = đại biểu (id) tự; fbSession = [Phiên FBSessionĐối với ứng dụng: SHKFacebookKey getSessionProxy: SHKFacebookSessionProxyURL delegate: delegate];

Nếu bạn chọn # 2, nó có thể giúp xác định các phương pháp thể hiện của giao thức sử dụng phương pháp lớp học, như vậy:

+ (void)protocolMethod { /* do stuff */ } 
- (void)protocolMethod { [self.class protocolMethod]; } 

đó cũng sẽ bao hàm bạn không bao giờ cần phải trường hợp. Nó sẽ giúp bởi vì nó sẽ thêm cảnh báo nếu giao thức sẽ thay đổi. Những cảnh báo này sẽ bong bóng lên đến các phương thức lớp khi bạn theo quy ước.

Để giảm tiếng ồn, bạn cũng có thể xem xét việc tạo một số phương pháp để giảm định kiểu cho một vị trí:

+ (id<SomeProtocol>)sharedSomeProtocolDelegate 
{ 
    return (id<SomeProtocol>)self; 
} 

- (id<SomeProtocol>)sharedSomeProtocolDelegate 
{ 
    return [[self class] sharedSomeProtocolDelegate]; 
} 

sau đó bạn chỉ có thể viết:

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

(lưu ý rằng việc triển khai của các loại này thực sự là các nhóm lớp và bạn sẽ thấy một thứ gì đó khác trong trình gỡ lỗi hoặc nếu được in)

+0

Chỉnh sửa của bạn làm rõ. Giao thức chỉ chứa các phương thức ví dụ và không có phương thức nào trong số chúng đề cập đến người nhận, bằng cách này. Tôi vẫn chưa rõ, tại sao tôi nhận được cảnh báo, nếu mã đáp ứng các tiêu chí bạn mô tả. – Jim

+0

@Jim detail added – justin

Các vấn đề liên quan