我在子类中重写了属性的设置器,但是当我在超类的init方法中调用它时,为什么子类的方法会响应?

时间:2018-08-03 13:32:58

标签: objective-c inheritance override

当我编写此代码时:

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

3 个答案:

答案 0 :(得分:2)

Sonself = [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