2017-07-15 69 views
1

我正在學習Swift編程語言,在此期間我有時會與舊的Objective-C編程語言及其代碼聯繫。Objective-C:用實例變量覆蓋Getter&Setter(使用_)

我是一個絕對的初學者,因此我有一些問題可以更好地理解Setter和Getter。

所以,我知道我可以通過大括號在.h文件中創建一個實例變量,但通常我使用屬性。這些屬性由實例變量支持,並自動提供Getter和Setter方法。

例子:

車輛的.h文件:

@interface Vehicle : NSObject 
@property int myProperty; 
@end 

因爲我創造了這個屬性我沒有申報getter和setter方法在vehicle.m文件,因爲它們是由編譯器自動創建。所以我可以創建一個車輛對象,設置並獲得價值。

的main.m

Vehicle *myvehicle = [[vehicle alloc] init]; 
[myvehicle myProperty] // myvehicle.myProperty 
[myvehicle setMyProperty : 10] // myvehicle.myProperty = 10; 

現在,我讀了它可以覆蓋自動創建Getter和我創造財產 「myProperty的」 的setter方法。當聲明我自己的Getter和Setter版本時,我必須在vehicle.h和vehicle.m文件中聲明兩個方法。在vehicle.m文件中,我不使用self關鍵字調用對象,而是使用它自動創建的實例變量(_myProperty)。這樣對嗎?

我試過了,但總是得到一個錯誤,我不知道爲什麼,什麼是重點。

車輛的.h文件:

@interface Vehicle : NSObject 
@property int myProperty; 
-(int) myProperty; //my new Getter method 
-(void) setMyProperty: (int)updatedMyProperty; //My new Setter method 
@end 

車輛.m文件:

@implementation Vehicle 

    -(int) myProperty { 
     if (! _myProperty) { 
     _myProperty = NO; 
    } 
     return _myProperty; 
    } 

    -(void) setMyProperty: (int)updatedMyProperty { 
    if (_myProperty == updatedMyProperty) return; 
    _myProperty = updatedMyProperty; 
    } 
    @end 

我總是得到錯誤 「使用未聲明的標識符的」 和我不不知道爲什麼。如果我理解正確,我不必使用@synthesize聲明ivar或其名稱,因爲編譯器會自動爲我創建名爲_myProperty的ivar。當我想改變伊娃的名字時,我只需要使用@synthesize。

我不知道爲什麼我卡住了,重點是什麼。你能解釋一下嗎? 在此先感謝!

+0

無關的,但上述你有'[myvehicle setMyProperty = 10] '。顯然這應該是'[myvehicle setMyProperty:10]'。 – Rob

回答

0

如果你實現了所有的存取方法,編譯器將不再爲你自動合成ivar。在這種情況下,你必須自己明確地這樣做。例如。

@synthesize myProperty = _myProperty; 

這隻在手動實現所有存取方法時纔有必要。原因是編譯器足夠聰明,知道如果你接管訪問器方法,你可能不需要伊娃,也就是說你可能會做一些完全不同的事情,例如,計算某些其他屬性的值,設置/從某個不同的商店中獲取值等。您可能希望編譯器綜合ivar(在這種情況下,您添加了以上@synthesize語句),但實現訪問者的可能性方法,因爲沒有需要支持伊娃(在這種情況下,你會省略上述@synthesize聲明)。

。不管怎麼樣,你簡單的例子住,你喜歡的東西:

@interface Vehicle : NSObject 
@property (nonatomic) int myProperty; // if you don't write atomic accessor methods, you really should be explicit that this is nonatomic 

// as an aside, even if you implement accessor methods, you don't have to declare them here 
// 
// -(int) myProperty; //my new Getter method 
// -(void) setMyProperty: (int)updatedMyProperty; //My new Setter method 

@end 

而且

@implementation Vehicle 

// since you implemented all of the accessor properties, you have to manually synthesize the ivar 

@synthesize myProperty = _myProperty; 

- (int) myProperty { 
    // do whatever you want here; note, the following doesn't make sense 
    // 
    // if (! _myProperty) { 
    //  _myProperty = NO; 
    // } 

    return _myProperty; 
} 

- (void)setMyProperty:(int)updatedMyProperty { 
    if (_myProperty == updatedMyProperty) return; 
    _myProperty = updatedMyProperty; 
} 
@end 

顯然,有以書面形式在上面的例子中,這些特定的訪問方法是沒有意義的,因爲你沒有提供任何新功能,所以你不會。您只需利用自動合成的存取器方法即可。

但是在那些你真的需要編寫自己的存取方法的情況下,你必須明確告訴編譯器是否需要它來爲你合成ivar。

+0

感謝您幫助和回答Rob!這真的幫助我瞭解幕後發生的原因和後果。在重寫getter和setter時,我不得不在我使用的書中聲明合成我的伊娃。所以,總結一下:在大多數情況下,我不需要綜合任何東西。如果我想重寫一個,getter或setter因爲我想實現更多的代碼,我不必做任何重寫。如果我想覆蓋兩者,我必須手動合成伊娃,但正如我之前所說,在大多數情況下,沒有必要這樣做。再次感謝! – Ari

-1

如果使用nonatomic屬性,則可以覆蓋getter或setter或兩者。編譯器會照顧其餘的。

@property (nonatomic) int yourInt; 

然後

-(int)yourInt 
{ 
// do something 
return _yourInt; 
} 

-(void)setYourInt:(int)someInt 
{ 
// do something 
_yourInt = someInt; 
} 

的註釋寫信getter或setter在.m文件到的這些差異:

_yourInt; //access variable directly 
[self yourInt]; // use getter method 

_yourInt = 4; // set vsriable directly 
[self setYourInt:4]; // use setter method 
+0

我沒有投票,但有兩件事:首先,'getYourInt'方法應該是'yourInt'。 Objective-C不像其他語言中那樣爲getter使用'get'前綴。事實上,這個拼寫錯誤是你的例子可能工作的唯一原因,因爲你沒有實現所有的訪問器方法,並且Xcode只有在你實現了所有的訪問器方法時纔會繞過伊娃綜合。其次,「原子」的規範是不相關的。 (實際上,當你忽略原子性限定符時,假定爲'atomic'。) – Rob

+0

感謝您的澄清! –

+0

好。但問題是現在你已經正確實現了'yourInt'和'setYourInt',這個ivar,'_yourInt'將不再爲你自動合成。事實上,這是OP的問題,也就是爲什麼它不能自動合成。 – Rob