【问题标题】:How does the designed initializer in Objective C work?Objective C 中设计的初始化器是如何工作的?
【发布时间】:2011-02-06 17:36:59
【问题描述】:

我一直在阅读这个问题,但没有得到它遇到的问题。 why does initializing subclasses require calling the super class's same init function?

根据我的阅读和理解。每个类都有自己设计的初始化程序。 在这种情况下,如果一个类有几个初始化器。假设我有一个像这样的“Shape.h”类。

- (id) init
{
    return [self initWithHeight: 0];
}

- (id) initWithHeight: (int) h
{
    return [self initWithHeight:h withWidth:0];
}

- (id) initWithHeight: (int) h withWidth: (int) w
{
    if(self = [super init]); //since the superclass is NSObject, I use init as designated initializer
    {
        [self setHeight:h];
        [self setWidth:w];
    }
return self
}

我从“Shape.h”类中继承了一个名为“Rectangle.h”的新类。 由于我将“Shape.h”指定为“-(id) initWithHeight: (int) h andWitdh: (int) w”,这意味着我需要将它用于“Rectangle.h”中的 [super init] “上课对吧?变成了这个样子。

- (id) initWithHeight: (int) h withWidth: (int) w
{
    return [self initWithHeight: h withWidth: w withColor:nil];
}

- (id) initWithHeight: (int) h withWidth: (int) w withColor: (NSString *) c
{
    if(self = [super initWithHeight:h andWidth:w])
    {
        [self setHeight:h];
        [self setWidth:w];
        [self setColor:c];
    }
return self;
}

在“Rectangle.h”中,我覆盖了指定 init 的 super(即 Shape.h)并自定义它以适应“Rectangle.h”指定的类。这种工作方式是否正确并且不会导致循环?如果是这样,任何人都可以在发布的链接中向我解释为什么如果我使用 [super init] 而不遵循指定的超类 init 会循环。

如果我造成任何混乱,我很抱歉。我不能很好地理解这个概念。

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    您的代码似乎是正确的,您尝试过吗? 指定的初始化程序是“最完整”的初始化程序,它应该被所有其他初始化程序使用。这是由 Rectangle 和 Shape 类完成的。 因此,您在 Rectangle init 中所做的是使用 super (Shape) 初始化程序来初始化您的类。然后检查 self 是否正确(由于任何原因 super 返回 nil 都可能发生,例如您的 w/h 参数不正确;但 Shape 并非如此)。然后你分配正确的颜色。 您不应该做的是重新分配高度和宽度,因为这已经由 Shape 初始化程序完成。仅当您的新类需要覆盖其超类的设置时才有意义(无论是什么原因)。 所以你的代码是正确的,但是去掉这两组:

    
    
            [self setHeight:h];
            [self setWidth:w];
    

    【讨论】:

    • 所以如果我在“Rectangle.h”类中使用指定的init,它会调用super init并使用指定的超类init来设置height和width的值。将值传递给当前类(子类),并将颜色的值分配给子类“Rectangle.h”。所以我只覆盖指定 init 的超类的方法在我的代码中是正确的吗?如果这是正确的,我可以将 "Rectangle.h" self=[super initWithHeight: (int) h andWitdth: w] 替换为 self=[super init] 因为超类最终会调用它指定的 init。
    • 不,不正确。事实上,如果 Rectangle initWithHeight:Width:Color 调用 [super init],那么反过来 Rectangle initWithHeight:Width 将被调用,它调用 Rectangle initWithHeight:Width:Color 从而导致循环。此外,您不会利用 Shape 的 initWithHeight:andWidth 执行的完整初始化。所以要非常小心并始终遵循这条规则(来自 Apple 的“The Objective-C 编程语言”:): 一般原则:类中的指定初始化程序必须通过向超级发送消息的方式调用超类中的指定初始化程序。跨度>
    • 这两行有什么区别? [super init] 和 [super initWithHeight:AndWidth:]。为什么后者不会导致循环?我的意思是,如果我使用 [super init],是不是会调用 Shape.h initWithHeight->initWithHeight:andWidth 以使它们相同?
    • 问题是如果你调用[super init]你会调用Shape的init,对吧?但 Shape 的 init 会调用 [self initWithHeight:0] 但“self”是 Rectangle。所以它会调用 Rectangle 的 initWithHeight:,它不存在,所以 Shape 的 initWithHeight: 会被调用。但是 Shape 的 initWithHeight: 调用 [self initWithHeight:h withWidth:0] 但 self 是 Rectangle 所以它会调用 Rectangle 的 initWithHeight:withWidth: 调用 [self initWithHeigth:withWidth:withColor:] 这是调用者 ==> 循环性。
    • 谢谢,我终于明白为什么会导致循环了。无论我是否从超类调用方法,Self 总是指向当前类(因为超类调用 self 调用了当前类 Rectangle)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 2011-09-08
    相关资源
    最近更新 更多