2012-11-22 37 views
1

我沒有什麼特別要實現,但我想了解更多關於類擴展。有關類擴展和繼承問題在Objective-C

這是類擴展直接從apple Categories and extensions的解釋:

@interface MyClass : NSObject 
@property (retain, readonly) float value; 
@end 

// Private extension, typically hidden in the main implementation file. 
@interface MyClass() 
@property (retain, readwrite) float value; 
@end 

它確實讓我感覺良好,但是,假如我有一個MyClass2延伸MyClass的:

@interface MyClass2 : MyClass 
@property (retain, readwrite) float value; 
@end 

,所以我有幾個問題,我可以很容易地回答,如果類延伸沒有涉及:

  • 在運行時,當MyClass的我做的轉讓self.value = 2或只是打電話浮動X = self.value,其中setter和getter @財產被稱爲? MyClass或MyClass2?
  • 不應該編譯器至少發出一個關於只讀屬性被重新定義的警告嗎?
  • 我知道@property是由伊娃支持的,所以最終有多少伊娃?與此相關,從MyClass2調用相同的self.value哪個ivar會設置?
+1

請不要將我的答案標記爲正確。我最初給出了錯誤的答案,並且只有在馬丁R讓我做對了之後才糾正它。 – emrys57

回答

1

首先,屬性應該是'賦值'而不是'保留',因爲它們是標量類型。

更改類擴展或子類中的可寫性是分別實現公共只讀但私有可寫屬性和不可變類的可變子類的常見模式。 Apple Objective-C編程指南有一個good discussion

要回答您的第一個問題,只有在MyClass中聲明的方法或其任何超類才能在MyClass中可見。你的私有類擴展聲明瞭實現的範圍,以便調用。 MyClass2的接口中的readwrite聲明僅僅將setter引入公共範圍。該實現仍然在MyClass中。

第二個問題的答案是否定的,不會發出警告。將可寫性從只讀改爲讀寫是有效的。

最後,只有一個伊娃。從MyClass2訪問它會影響MyClass中可見的同一個ivar。

+0

我沒有注意到,我同意你的標量類型,但是這是一個來自蘋果文檔的示例:-) – Leonardo

+0

在這一點上,我想知道類擴展的好處是什麼,如果我可以擴展一個類並進行轉換隻讀給公衆。消除保護只讀屬性的目的。 – Leonardo

0

您不能retain a float。改爲寫(readonly)

MyClass不知道任何關於MyClass2,這似乎是MyClass的子類。當您編寫self.value = 2時,它將被轉換爲[self setValue:2],代碼將從MyClass開始並查找setValue方法。這將會被創建,因爲您將value定義爲屬性。 setter方法將看起來像

-(void) setValue:(int newValue) { 
     _value = newValue; // _value is the actual storage for the property value 
} 

和可變_value將是您正在執行的對象MyClass的實例分配的一個。

實際上只有一個iVar。如果,在MyClass2,你寫

self.value = 3; 
super.value = 4; 
float myFloat = self.value; 

myFloat最後等於4

想必編譯器不會抱怨MyClass重新定義屬性,因爲它是相當合理的事情。這樣,其他班級不能寫入value,但在MyClass內,您可以編寫self.value = 2;,它將工作。

我確實相信有兩個iVar,但我錯了。抱歉讓任何人困惑。感謝Martin R和BradS對我的教育。

+0

這個答案不正確。 value屬性的子類中沒有第二個ivar,並且子類沒有單獨的存取器函數。即使'anObject'是'MyClass2'的一個實例,'anObject.value'將始終引用'MyClass'中的存取器函數。 –

+0

但是我編譯並運行了它,並且有兩個! – emrys57

+0

我不明白你的例子。如果你有兩個不同的對象(object1和object2),那麼當然每個對象都有自己的實例變量。 –