Objective-C:用实例变量覆盖Getter&Setter(使用_)

问题描述:

我正在学习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

如果你实现了所有的存取方法,编译器将不再为你自动合成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

如果使用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