Objective-C:覆盖Getter&具有实例变量的setter(使用_)

时间:2017-07-15 15:10:15

标签: objective-c oop override getter-setter

我正在学习Swift编程语言,在此期间我有时会接触旧的Objective-C编程语言及其代码。

我是一个绝对的初学者,因此我有一些问题需要更好地了解Setter和Getter。

所以,我知道我可以通过.h文件中的花括号创建一个实例变量,但通常我会使用属性。这些属性由实例变量支持,并自动提供Getter和Setter方法。

示例:

车辆.h文件:

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

因为我创建了这个属性,所以我不必在vehicle.m文件中声明Getter和Setter方法,因为它们是由编译器自动创建的。所以我可以创建一个车辆对象,设置并获得价值。

示例

的main.m

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

现在我读到可以覆盖我创建的属性" myProperty"的自动创建的Getter和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

vehicle .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。当我想改变ivar的名字时,我只需要使用@synthesize。

我不确定为什么我会被卡住,重点是什么。你能解释一下吗? 提前谢谢!

2 个答案:

答案 0 :(得分:2)

如果实现所有访问器方法,编译器将不再自动为您合成ivar。在这种情况下,您必须自己明确地这样做。 E.g。

@synthesize myProperty = _myProperty;

仅在手动实施所有访问者方法时才需要这样做。原因是编译器足够聪明,知道如果你接管访问器方法,你可能不需要ivar,即你可能正在做一些根本不同的事情,例如:从一些其他属性计算值,从某些不同的商店设置/获取值等等。您可能希望编译器合成ivar(在这种情况下,您添加上面的@synthesize语句),但它同样可能是你'我实现了访问器方法,因为不需要支持ivar(在这种情况下,你省略了上面的@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。

答案 1 :(得分:-1)

如果使用非原子属性,则可以覆盖getter或setter或两者。编译器将负责其余的工作。

@property (nonatomic) int yourInt;

然后在.m文件中写入getter或setter

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

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

注意到这些差异:

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

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