2012-01-08 48 views
3

有3個修飾符:@private,@protected(默認)和@public。所以如果我將一個實例變量定義爲私有的,那麼不應該從任何地方訪問它。 例如 -目標c中的訪問修飾符可見性

@interface A { 
    @private 
    NSString *a; 
} 
@property(nonatomic, retain) NSString *a; 

現在裏面實現一些其他的接口/類B-

-(void)getSomeValue { 
    A *object = [[A alloc] init]; 
    NSString *value = object.a; 
    ......... 
} 

這裏,我能夠訪問實例變量,雖然我定義爲私有。

這有點令人困惑,雖然當我仔細研究這個語句的細節時,很明顯它調用了a的getter,但是它也似乎令人困惑,並且它違背了OOPS的概念。

任何人有任何想法呢?

+1

而@package制約可視性的框架。 – Abizern 2012-01-08 17:43:38

回答

10

這不是您訪問的實例變量,而是您聲明的屬性。如果您不希望實例變量在類之外可見,則不要聲明該屬性。

+0

我的問題基本上是如果我能夠訪問外部私人變量那麼什麼是重要的呢? – rishi 2012-01-08 17:33:08

+9

同樣,您沒有訪問私有變量。你宣稱它是這個類的一個屬性。所以你爲它產生了一個getter和一個setter。該變量仍然是私有的。訪問方法不是。 – tobiasbayer 2012-01-08 17:38:44

+1

CodeBrickie - 謝謝......現在我知道了......我想我對語法有點困惑...... – rishi 2012-01-09 16:17:23

-2

因爲您將其設置爲@property並在頭文件中聲明它。您設置爲@property的變量將自動爲此變量生成getter和setter,並且它們都是公共方法來獲取或設置它(變量仍然是私有的)。如果你真的想把這個屬性作爲私有方法,你應該在.m文件中聲明它,它將變成私有的。您只能在.m文件中使用此變量。

例如,在您的.m文件

#import "ClassWithPrivateProperty.h" 

@interface ClassWithPrivateProperty() 
@property (nonatomic,retain) NSString* member; 
@end 

@implementation ClassWithPrivateProperty 
@synthesize member; 
- (void) trySettingPrivateProperty { 
    self.member = @"A Value"; 
    NSLog(@"myClass.member = %@", self.member); 
} 
@end 

您的.h文件中

@interface ClassWithPrivateProperty : NSObject { 
@private 
    NSString* member; 
} 
- (void) trySettingPrivateProperty; 
@end 

您可以查看更詳細Private properties for iPhone Objective-C

編輯:

感謝Abizern和Paul的評論,但實際上我沒有爲這個程序編譯錯誤米

我覺得RIP的問題是:「爲什麼我設置在@private變量,但我仍然可以修改變量像instance.variable」

答案是雖然他設置變量爲@private,但要求@property爲.h文件中的變量提供公共方法getter和setter。所以他仍然可以使用instance.variable獲取實例變量。對於OOP設計模式,你不應該公開你的內部。所以如果你只想在其類中私下使用一個變量,而且沒有人知道它。你仍然想使用getter和setter來訪問它的類中的這個變量。你應該在.m文件中聲明@property,就像我上面所做的那樣。我在.m文件中聲明@property,它是@interface擴展名(未命名的類別)。所以你可以使它「像」私人。因爲您無法從此課程以外的任何地方訪問此變量。所以這就像我提到的「私人@屬性」。

兩個有用的文章對您Public Properties with Private SettersPrivate properties for iPhone Objective-C

+3

你不能使私有'@財產'的。你可以隱藏它的可見性,但沒有什麼能阻止我從任何地方調用'[instance member];'。 – 2012-01-08 17:57:16

+0

保羅的權利。你會得到一個編譯器警告,但沒有什麼可以阻止郵件被髮送。 – Abizern 2012-01-08 21:37:07

8
#import <Foundation/Foundation.h> 

@interface Visibility : NSObject { 
@public  
    BOOL boolPublic; 
@protected 
    BOOL boolProtected; 
@private 
BOOL boolPrivate; 
} 

@property (nonatomic, assign) BOOL boolPublic; 
@property (nonatomic, assign) BOOL boolProtected; 
@property (nonatomic, assign) BOOL boolPrivate; 

@end 

@implementation Visibility 

@synthesize boolPublic; 
@synthesize boolProtected; 
@synthesize boolPrivate; 

@end 

int main(int argc, char *argv[]) { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    Visibility *visibility = [[Visibility alloc] init]; 

    visibility.boolPublic = YES; 
    visibility.boolProtected = YES; 
    visibility.boolPrivate = YES; 

    // Place following NSLog()'s here 

    [pool release]; 
} 

讓我們試試這個

使用您定義的方法@財產/ @合成

NSLog(@"Accessors %d %d %d", visibility.boolPublic, visibility.boolProtected, visibility.boolPrivate); 

=> 2012-01-08 17:46:40.226 Untitled[2592:707] Accessors 1 1 1 

訪問@公共伊娃直接

NSLog(@"Public %d", visibility->boolPublic); 

=> 2012-01-08 17:46:40.228 Untitled[2592:707] Public 1 

訪問@protected伊娃直接

NSLog(@"Protected %d", visibility->boolProtected); 

=> error: instance variable 'boolProtected' is protected 
=> NSLog(@"Protected %d", visibility->boolProtected); 
=>         ^

訪問@private伊娃直接

NSLog(@"Private %d", visibility->boolPrivate); 

=> error: instance variable 'boolPrivate' is private 
=> NSLog(@"Private %d", visibility->boolPrivate); 
=>        ^

當您使用點表示法訪問此:

visibility.boolPublic 

等同於:

[visibility boolPublic]; // <- This is a method call