我的情况是我的子类没有看到超类'实例变量x
。默认情况下,ivar显然是@protected
,那么为什么我会得到编译器错误“x undeclared”?
- (CGSize)hitSize
{
// Compiler error
return size;
}
编辑:hitSize是我的子类符合的协议的属性。问题是我遇到了@synthesize
d,这是罪魁祸首。那么问题是为什么合成的吸气剂不能看到ivar?
答案 0 :(得分:3)
Joanna的答案都是正确的(尽管ivar综合并没有在32位Mac OS X上发挥作用)。
但是,原因是因为允许子类合成对超类内部状态的访问会非常明显地破坏封装。决定在所有情况下都明确禁止该特定模式,即使在单一框架内也是如此。
如果超类为某些东西提供存储,它应该提供访问控制并封装所述内存的管理。如果子类需要自定义访问权限,请通过重写getter / setter [并且最好调用super来实际获取/设置值]来这样做。
答案 1 :(得分:2)
你也可以使用显式的getter / setter属性来访问,甚至是基类的@private ivars:
@interface Base : NSObject { @protected int intVar; } @end @interface Derived : Base { } @property (assign, getter = intVar, setter = intVar) int aVar; @end
答案 2 :(得分:1)
合成属性不仅合成了getter和setter,如果没有声明,它们也会合成ivar。
您需要在子类中编写显式访问器,并通过self-> myIvar语法访问@ protected ivar。
答案 3 :(得分:1)
感谢bbum,详细说明我的回复。
关于你的第二个回复,你当然是正确的,在这种情况下,你可以“做正确的事”,使用类扩展来隐藏基类上的属性,如下所示:
// Example.h @interface Base : NSObject { @private int intVar; } @end @interface Derived : Base { } @property (assign) int aVar; @end
// Example.m @interface Base () @property (assign) int intVar; @end @implementation Base @synthesize intVar; @end; @implementation Derived - (int) aVar { return self.intVar; } - (void) setAVar:(int)value { self.intVar = value; } @end