2011-12-14 68 views
11

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

考虑这个例子:

// 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

这是[Kevin Ballard的回答](http://stackoverflow.com/a/8511046/)解释为[合成ivars的可见性是多少?](http://stackoverflow.com/questions/8510464/) )从几个小时前。 – 2011-12-14 21:46:43

回答

11

您还没有真正定义的变量,你只定义一个财产(其隐含地定义一个变量,它是私有的)。由于属性只是方法,你需要点语法。请注意0​​与[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可可注意但如果你使用属性保留。而@NSGod是正确的,默认的实例变量是保护默认,而不是公开,固定的。

+1

`@综合'属性实际上确实创建了他们的名字的伊娃,但他们综合了一个@私人的伊娃。你回答的工作是因为你已经专门创建了伊娃,并将合成器分配给了一个限制较少的访问级别,这并不是因为合成器不生成Ivars。 – 2011-12-14 21:50:58

8

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

例如,为了能够直接引用实例变量,你需要进行以下更改:

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

到:

​​

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