2011-12-14 54 views
16

如果您有類似下面@synthesized實例變量的可見性是什麼?

@interface MyClass : NSObject 
@property(strong) NSString *myProp; 
@end 

你的公共接口屬性,然後合成它,實際上合成變量:

@implementation MyClass 
@synthesize myProp = _myProp; // or just leave it at the default name.. 
@end 

什麼是實例變量_myProp知名度?也就是說,這是否被認爲是@public,@protected@private?我猜是因爲MySubClass可以從MyClass繼承,那麼它也會獲得屬性(自然),但它是否也會繼承實例變量的可見性?

如果我將該屬性放入類擴展中,它會產生什麼區別?這會隱藏子類的屬性,我也在猜測實例變量。這是記錄在任何地方?

回答

28

一個合成的伊娃是完全看不見所有的代碼,看不到@synthesize行(基本上意味着.m文件之外的任何東西)。這不是@protected,它不是@private,它只是未知數。使用一個@private伊娃,其他代碼試圖訪問它將被告知它是私人的,但是對於一個合成的伊娃,其他代碼試圖訪問它將被告知該字段根本不存在。

作爲一個思想實驗,嘗試想象一下,伊娃採取的行爲就像是@protected。你創建了一個子類,然後你在那裏與伊娃混在一起。現在你回到超類,並將@synthesize myProp更改爲@synthesize myProp=foo。子類會發生什麼?當編譯器處理子類時,它看不到@synthesize行,所以它不知道你只是改變了伊娃的名字。事實上,它甚至無法說明該財產是否完全由伊娃支持,或者是否通過自定義編寫的訪問方法實施。我希望這很明顯,這意味着爲什麼這意味着子類不可能訪問伊娃,而其他任何一類都不可能。

這就是說,我不太清楚編譯器如果在試圖訪問伊娃的相同.m文件中編寫代碼。我期望它會將伊娃視爲@private(因爲編譯器實際上可以看到伊娃存在)。

此外,這些對運行時方法沒有任何影響。其他類仍然可以使用obj-c運行時方法來動態查找您的類的ivar列表,​​並仔細查看它。

+6

很好解釋! – 2011-12-14 20:19:12

1

如果它是在您的界面中聲明的,它在使用@property聲明時幾乎是公開的。如果你想使用@property聲明,並保持它們的屬性真正私有,你應該在你的實現中創建一個私有類。

MyClass.h

@interface MyClass : NSObject { 
@private 
    NSObject* foo; 
} 
@end 

MyClass.m

#import "ClassWithPrivateProperty.h" 

@interface MyClass() 
    @property (nonatomic,retain) NSObject* foo; 
@end 

@implementation MyClass 
@synthesize foo; 
// class implementation... 
@end 
+1

很好的建議,但沒有提到伊娃自身的知名度。 – 2011-12-14 20:13:11

+1

你的回答並沒有真正解決支持ivar _itself_的可見性。 – 2011-12-14 20:18:10

1

一個合成的變量就如同宣佈@private

@interface Garble : NSObject 
@property (copy) NSString * s; 
@end 
@implementation Garble 
@synthesize s; 
@end 

@interface Bargle : Garble 
@end 

@implementation Bargle 

- (void) useS { 
    NSLog(@"%@", s); // error: instance variable 's' is private 
} 

@end 

我發誓我見過這在the docs,但我現在找不到它。如果我追蹤它,將會更新。

0

其他類可以訪問它們的所有內容#include。換句話說,就是你的標題中的所有內容。

如果某些內容僅出現在您的實現文件中,其他類(包括子類)不知道它存在。綜合性質就是這樣。其他類只知道屬性(屬性意味着一個getter和一個setter方法),但他們不知道其方法的內部實現。

請注意,obj-c中的訪問說明符(public/private/protected)僅是編譯器的一個提示,即使頭文件中出現某些內容,也無法訪問它。運行時不會以任何方式檢查它。

如果將其放入類擴展中會發生什麼?請注意,屬性是一組兩種方法。您只需隱藏每個包含您的類主標題但不包含類擴展標題的類的方法。

我們使用這個例子來聲明一個屬性爲只讀屬性,並在類繼續中聲明它爲readwrite。然後,我們只能從課堂內部使用setter。

1

您可以創建一個動態屬性,並向編譯器指出它的實例化將在運行時。

然後在你的子類中編寫自己的getter或綜合屬性。

@interface BaseClass的:NSObject的

@屬性(非原子,強)的NSString * ThisWillBeSynthesizedInRespectiveSubclasses;

@end

@implementation BaseClass的

@dynamic ThisWillBeSynthesizedInRespectiveSubclasses;

@end

在子類

@interface亞綱:BaseClass的

@end

@implementation子類 @synthesize ThisWillBeSynthesizedInRespectiveSubclasses = _ThisWillBeSynthesizedInRespectiveSubclasses;

@end

或者您編寫自己的setter/getter方法。

希望這會有所幫助!