当我编写此代码时:
//Father.m
@implementation Father
- (instancetype)init {
if (self = [super init]) {
self.name = @"super class";
}
return self;
}
- (void)setName:(NSString *)name {
_name = [name copy];
NSLog(@"super class");
}
@end
,在子类“ Son”中,我重写了方法“ setName:”:
@synthesize name = _name;
- (instancetype)init {
if (self = [super init]) {
self.name = @"sub class";
}
return self;
}
- (void)setName:(NSString *)name {
_name = [name copy];
NSLog(@"sub class");
}
当我这样称呼时:
Son *s = [[Son alloc] init];
它打印此:
sub class
sub class
为什么不呢?
super class
sub class
谁能解释为什么两次调用子类的setter?
答案 0 :(得分:2)
当Son
在self = [super init]
调用- init
时,将调用父亲的init
方法,但是在Father
的{{1}}方法中,{ {1}}表示- init
的时间,因为self
只是编译器的关键字。在运行时阶段,实际上是Son
函数发送的消息,super
是一个结构,其第一个参数是objc_msgSendSuper
结构指针,在结构内部,第一个成员是{{ 1}},即objc_msgSendSuper
。
objc_super
答案 1 :(得分:1)
self.name = @"super class"
类中的语句Father
调用由setName
类实现的Son
setter,因为Son
覆盖了它。因此,它跳回到了继承类。那就是继承的好处。如果您想使事情分开,请不要使用继承。
注意:您仍然可以通过从setName
调用Father
来访问在[super setName:]
中实现的Son
。但是,如果您在Father
的初始化程序中使用它,它将尝试访问父亲的超类,该父类可能是NSObject
。
答案 2 :(得分:1)
它打印
sub class
sub class
因为当您输入父亲的初始化时,self
的类型为Son
,因此self.name
上的呼叫将呼叫Son
上的二传手而不是父亲。因此,永远不会调用Father
上的二传手。您可以通过将Father
上的init修改为:
- (instancetype)init {
if (self = [super init]) {
NSLog(@"%@", NSStringFromClass([self class]));
self.name = @"super class";
}
return self;
}
然后您会看到self
实际上是Son
而不是Father