2016-05-31 128 views
1

我在School類具有可變mTeacher一個實例:分配一個實例變量本身

@interface School : NSObject { 
    Teacher *mTeacher; 
} 
@end 

在實現文件中,我有方法- (Teacher *)getTeacher這應該返回任何現有的教師來說,如果有一個或創建一個並返回它:

- (Teacher *)getTeacher { 
    if (mTeacher != nil) { 
     return mTeacher; 
    } 
    return [[Teacher alloc] init]; 
} 

可能有其他多個實例的方法調用此方法來獲取Teacher實例&分配到mTeacher實例變量:

- (void)methodOne { 
    mTeacher = [self getTeacher]; 
    ... 
} 

- (void)methodTwo { 
    mTeacher = [self getTeacher]; 
    ... 
} 

所以,如果分配的方法之一已經是Teacher一個實例mTeacher,呼籲[self getTeacher]當其他方法最終會與mTeacher = mTeacher下(因爲- (Teacher *)getTeacher方法只是在這種情況下返回mTeacher) 。我的問題是,在Objective-C中很好嗎?我的getTeacher方法有任何潛在的問題?

+0

您正在實施Singleton設計模式。這裏的另一個相關的帖子應該有所幫助:http://stackoverflow.com/questions/145154/what-should-my-objective-c-singleton-look-like –

+1

我沒有看到任何技術上的錯誤,但爲什麼不只是初始化一個'init'方法中的變量並在需要的地方使用它,而不是試圖多次設置? (在風格上:與Objective-C相比,將教師作爲一個屬性而不是一個顯式變量更符合我的想法,然後,再加上我對'init'的建議,「getter」會從你的代碼中消失。) –

+0

如果'mTeacher'永遠不是'nil',爲什麼不用''''init'方法初始化它呢?另外,你應該檢查出[Objective-c中的屬性](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html) – Sudo

回答

0

這是很好的目標c .. !!你不應該有問題,有了這個,我想,但你可以檢查與是否 - 別的喜歡,

- (void)methodOne { 

    if(!mTeacher){ 
    mTeacher = [self getTeacher]; 
    } 
    ... 
    } 

所以,如果mTeachernil那麼只有它會叫getTeacher

在目標c中,您可以使用property。它會設置它的getter和setter方法。或者你需要這個對象在init方法中初始化一次。沒有必要這樣做。

1

它看起來像你想懶惰地實例化變量。

Objective-C中的常用模式是聲明只讀(非原子)屬性並使用支持實例變量進行初始化。

@interface School : NSObject 

@property (readonly, strong, nonatomic) Teacher *mTeacher; 

@end 

@implementation School 
@synthesize mTeacher = _mTeacher; 

- (Teacher *)mTeacher { 
    if (!_mTeacher) { 
     _mTeacher = [[Teacher alloc] init]; 
    } 
    return _mTeacher; 
} 

@end 

編輯:如果不使用屬性訪問實例變量直接:

@interface School : NSObject 
{ 
    Teacher *mTeacher; 
} 

@end 

@implementation School 

- (Teacher *)mTeacher { 
    if (!mTeacher) { 
    mTeacher = [[Teacher alloc] init]; 
    } 
    return mTeacher; 
} 

@end 

但是如果你想要明確地使用吸氣,而不是你有實例變量寫

[self mTeacher]; 
+0

我會很感興趣要知道該版本不使用'@ property'進行延遲初始化,請問您能否告訴我一下? –

+0

我增加了一個例子 –

+0

@vadian你的例子不會編譯,因爲如果覆蓋所有訪問器,則不會隱式創建ivar。 –

0

這種方法沒有錯,爲什麼你不能在School init中創建Teacher對象。而且,如果您正在研究多線程環境,請確保您沒有多次創建教師對象。

+0

你說得對,代碼不是線程安全的。但是,在許多情況下僅使訪問器是線程安全的是沒有意義的。 (這就是爲什麼幾乎沒有人使用原子訪問器。)但是,如果你想擁有線程安全性,現在應該使用GCD。 –

+0

我的意思是我們應該保護我們正在創建實例的地方(init方法),而不是訪問者。 – Feroz

+1

@Feroz:惰性初始化非常有用,在許多情況下非常重要。 – gnasher729

1

的方法是正確的,但有兩個備註:

A.你永遠不能擁有一個「無老師」 scheool,這意味着物業nil'd - 不管是什麼。

B.很明顯,你開始與Objective-C的另一種語言來:

  • 不要使用m前綴 「成員」。 (他們不是成員,但是艾瓦爾。)

  • 不要在接口中聲明ivars。

  • 請勿爲獲取者使用前綴get

您可以使用性能,如vadian提到:

@interface School : NSObject 
@property (readonly, strong, nonatomic) Teacher *teacher; // without m 
- (Teacher*)teacher; // *Alternatively* without @property 
@end 

@implementation School 
// usually the ivar is created implicitly with the name _teacher. 
// However, you have a readonly property and overwrite all accessors 
// (in the case of a read only property there is only a getter) of the property, 
// no ivar will be created automatically. You have to do that explicitly. 
{ 
    Teacher *_teacher; 
} 

- (Teacher *)teacher { // no m 
    if (!_teacher) 
    { 
    _teacher = [[Teacher alloc] init]; 
    } 
    return _teacher; 
} 
@end 

此外,該代碼不是線程安全的。