在Objective-c中继承实例变量

时间:2011-12-14 21:32:31

标签: objective-c inheritance instance-variables self

在Objective-c 2.0中,为什么子类需要使用self关键字在父类中引用实例变量?

考虑这个例子:

// a.h
@interface MyClass : NSObject
@property (nonatomic, retain) Object *myObject;
@end

// a.m
@implementation MyClass
@synthesize myObject;
@end


// b.h
@interface AnotherClass : MyClass
@end

// b.m
@implementation AnotherClass
- (void) someMethod {
    // error
    // Object *obj = myObject;

    // works
    // Object *obj = self.myObject;
}
@end

2 个答案:

答案 0 :(得分:13)

您实际上没有定义变量,您只定义了一个属性(它隐式定义了一个私有变量)。由于属性只是方法,因此需要点语法。请注意,self.property[self property]相同。

要解决此问题,请指定一个变量。我将举例说明变量的名称与属性不同。大多数人为两者选择了相同的名称,但我喜欢让它们有所不同,所以我立刻就会看到它的含义。

// a.h
@interface MyClass : NSObject {
    // Instance variables are "protected" by default, except if you
    // use @private or @public.
    Object *myObjectVar;
}

@property (nonatomic, retain) Object *myObject;
@end

// a.m
@implementation MyClass
@synthesize myObject = myObjectVar;
@end


// b.h
@interface AnotherClass : MyClass
@end

// b.m
@implementation AnotherClass
- (void) someMethod {
    // works
    Object *obj = myObjectVar;

    // works
    obj = self.myObject;

    // the same as self.myObject
    obj = [self myObject];
}
@end

注意分配时的区别:如果分配给变量,则不会自动保留对象。但如果您使用该属性,它将被保留:

myObjectVar = someObject; // not retained, old object not released!
self.myObject = someObject; // old object released, new object retained
[self setMyObject:someObject]; // same as the line above

编辑:提到合成的实例变量默认是私有的,如@Jason Coco所述。并且@NSGod是正确的,正常的实例变量默认是受保护的而不是公共的,修复了它。

答案 1 :(得分:8)

如果您实际在超类中声明了一个实例变量,它们不会,而不是依赖新运行时的合成实例变量的能力(除了合成访问器方法)。有关实例变量合成的更多信息,请参阅The Objective-C Programming Language: Runtime Difference

例如,为了能够直接引用实例变量,您需要更改以下内容:

@interface MyClass : NSObject
@property (nonatomic, retain) Object *myObject;
@end

为:

@interface MyClass : NSObject {
// there is an implied @protected directive here
    Object *myObject;
}

@property (nonatomic, retain) Object *myObject;

@end

默认情况下,实例变量为@protected,这意味着类和任何子类都可以直接访问实例变量。 @protected ivars与@public ivars的不同之处在于您无法使用->访问它们。 @private ivars只能由声明它们的类访问。有关详细信息,请参阅The Objective-C Programming Language: The Scope of Instance Variables