簡體   English   中英

聲明變量協議的目的是什么?

[英]What is the purpose of declaring a protocol for a variable?

我一直在閱讀有關Objective-C的協議,但我不能理解這一點:

考慮這條線

Person <CoordinateSupport> *person = [[Person alloc] init];

聲明變量符合協議CoordinateSupport的目的是什么? 這是否僅用於編譯時,如果我person分配了其他內容,或者在運行時有任何目的,Xcode會警告我嗎?

我看不到變量如何符合協議。 好的,一個類很容易看到,因為您可以有一個協議來定義您希望某個類遵循但ivar可以遵循的方法。

我沒看到

聲明變量符合協議時的標准模式是為其賦予“任何對象”類型id 聲明變量既具有特定類型符合協議通常是多余的–稍后將解釋原因。 現在,讓我們討論一下id<P>類型的變量(其中P是某種協議)以及它們為什么有用的原因。 該類型應理解為“符合P的任何類的實例”。

為了具體化下面的討論,讓我們定義一個協議:

@protocol Adder
- (NSInteger)add:(NSInteger)a to:(NSInteger)b;
@end

我看不到變量如何符合協議。

這很容易。 當變量表示實現協議中所有必需方法的類的實例時,它符合Objective-C協議。

@interface Abacus : NSObject <Adder>
@end

@implementation Abacus
- (NSInteger)add:(NSInteger)a to:(NSInteger)b { return a + b; }
- (NSInteger)beadCount { return 91; }
@end

鑒於此Abacus課程,您當然可以創建一個新的Abacus

Abacus *a = [[Abacus alloc] init];
NSLog(@"%ld", (long)[a add:5 to:6]);  // 11
NSLog(@"%ld", (long)[a beadCount]);   // 91

但您也可以聲明a只是id<Adder類型。 請記住,這意味着類型a為“符合任何類的一個實例Adder 。”

id<Adder> a = [[Abacus alloc] init];
NSLog(@"%ld", (long)[a add:5 to:6]);  // 11
NSLog(@"%ld", (long)[a beadCount]);   // Compile error: No known instance method for selector 'beadCount'

編譯器會抱怨,因為我們所有說過的類型a是,它是符合一類Adder ,無處在Adder協議做我們說一個叫什么方法beadCount

聲明變量符合[協議]的目的是什么?

目的是為了隱藏信息。 當您想要一個符合Adder的類時,無需關心實際的類是什么–您只需獲得一個id<Adder> 假設Abacus是一個系統類,您已經編寫了以下代碼:

- (Abacus *)getAdder { return [[Abacus alloc] init]; }
- (void)doWork {
    Abacus *a = [self getAdder];
    // Do lots of adding...
}

然后,在iOS 42中,Apple提出了一項新的創新– Calculator類! 您的朋友告訴您, Calculator將兩個數字相加的速度是Abacus兩倍多,而所有很酷的孩子都在使用它! 您決定重構代碼,但是您意識到,不僅必須更改getAdder的返回類型,而且還必須更改為其分配getAdder的返回值的所有變量的類型! 瘸。 如果您改為這樣做,該怎么辦:

- (id<Adder>)getAdder { return [[Abacus alloc] init]; }
- (void)doWork {
    id<Adder> *a = [self getAdder];
    // Do lots of adding...
}

現在,當您要遷移到Calculator ,只需要更改getAdder的主體以return [[Calculator alloc] init]就可以了! 一條線。 您的其余代碼完全相同。 在這種情況下,您將從其余代碼中隱藏了從getAdder返回的實例的真實類型。 信息隱藏使重構更加容易。

最后,我答應解釋一下為什么Abacus <Adder> *a = ...的東西通常是多余的。 您在這里所說的是“ a是符合AdderAbacus實例”。 但是您(和編譯器)已經知道Abacus符合Adder -它就在接口聲明中! 正如rmaddy指出的那樣 ,在某些情況下,您想談論一個既是給定類,又是其子類的實例,並指定它符合協議,但是這種情況很少見,通常都指定兩者不需要類和協議一致性。

有關更多信息,請查閱Apple的“使用Protcols”指南。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM