我最近意识到使用self.whatever = thing从init内部访问类的属性不是正确的形式,而是应该使用_whatever = thing直接访问属性。当我设置基类的值时,这很好用。但是,当我尝试在子类的init中设置值时,我得到错误"使用未声明的标识符_whatever"。使用self.w从子类的init内部工作正常。
为了清楚起见,对于@property int在基础对象的接口中声明的内容,这个编译:
-(id) init {
self = [super init];
if (self) {
[self createName];
self.whatever = 100;
}
return self;
}
这并不是:
-(id) init {
self = [super init];
if (self) {
[self createName];
_whatever = 100;
}
return self;
}
我想我在这里误解了一些东西。我试着搜索我做错了什么,但我不知道要搜索的正确单词。
根据要求,基类的标题:
#import <Foundation/Foundation.h>
@interface DTCharacter : NSObject
@property BOOL isIdle;
@end
我使用自动合成,因此在基类的实现中没有关于此变量的内容。
子类的头文件也没有提及或引用该变量。
我试图在子类的实现中分配它:
-(id) init {
self = [super init];
if (self) {
[self createName];
_isIdle = YES; //says use of undeclared identifier
//this would work: self.isIdle = YES;
}
return self;
}
答案 0 :(得分:5)
如果属性,访问init
或dealloc
中的属性可能会有问题
访问器方法对对象的 state 进行假设,这可能不是
在部分构造的对象中实现。
但这仅适用于类本身的属性,而不适用于类的属性 超类。之后
self = [super init];
self
的“超级部分”已完全构建,因此可以安全地调用
self.whatever = 100;
在子类init方法中,设置在超类中声明的属性。
_whatever = 100;
在子类中不起作用,因为自动合成的实例变量 仅在超类本身中可见。您可以明确声明它来实现它 对子类可见,但没有必要这样做。
答案 1 :(得分:2)
Martin的回答是最好的,因为你真的不需要为超类属性做这个(并且可能不应该,基于类实现应该是私有的理论,甚至从子类到可能的程度)。但是,如果你想这样做,这里有一个例子来说明:
的main.m:
#import <Foundation/Foundation.h>
#import "PGRBase.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
PGRChild * theObject = [PGRChild new];
NSLog(@"Property is %d\n", theObject.prop);
}
return 0;
}
PGRBase.h:
#import <Foundation/Foundation.h>
@interface PGRBase : NSObject {
int _prop;
}
@property (readwrite, nonatomic, assign) int prop;
@end
@interface PGRChild : PGRBase
@end
PGRBase.m:
#import "PGRBase.h"
@implementation PGRBase
- (instancetype)init
{
self = [super init];
if ( self ) {
_prop = 1;
}
return self;
}
@end
@implementation PGRChild
- (instancetype)init
{
self = [super init];
if ( self ) {
_prop = 2;
}
return self;
}
@end
NSLog()
通话记录Property is 2
。
答案 2 :(得分:0)
有一些代码片段可以让子类可以访问ivars:
@interface SomeBase : NSObject
{
@protected
WhateverType* _whatever;
}
@end
因此_whatever
的子类将显示SomeBase
。