[英]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
是符合Adder
的Abacus
實例”。 但是您(和編譯器)已經知道Abacus
符合Adder
-它就在接口聲明中! 正如rmaddy指出的那樣 ,在某些情況下,您想談論一個既是給定類,又是其子類的實例,並指定它符合協議,但是這種情況很少見,通常都指定兩者不需要類和協議一致性。
有關更多信息,請查閱Apple的“使用Protcols”指南。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.