是不是可以在Objective-C中链接初始化器?

Ser*_*nce 0 cocoa cocoa-touch objective-c

我在用于iPhone的Objective-C/Cocoa-Touch编码,我想知道,不链接​​初始化器是否可行?例如,在我的父类中,我有三个初始化器,它们都需要由子类继承.在这种情况下可以不链接吗?例如,在这一个课程中我设置如下:

- (id)initWithGraphic:(Graphic*)graphic size:(CGSize)size
{
    self = [super initWithFrame:CGRectZero];
    if (self) 
    {
      ...

    }
    return self;
}

- (id)initWithGraphic:(Graphic*)graphic maximumDimension:(CGFloat)maximumDimension
{
    self = [super initWithFrame:CGRectZero];
    if (self) 
    {
      ...

    }
    return self;
}

- (id)initWithGraphic:(Graphic*)graphic 
{
    self = [super initWithFrame:CGRectZero];
    if (self) 
    {
      ...

    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

所以基本上我没有一个指定的初始化器,因为我很难把它们连在一起,我基本上有三个.

rob*_*off 6

简短回答:如果您希望您的代码易于理解和维护,那么您必须始终调用super指定的初始化程序.

答案很长......

记录该-[NSObject init]方法无效:

该类中init定义的方法NSObject不进行初始化; 它只是返回self.

因此理论上你不需要调用它.在实践中,最好调用它,因为它使您的代码更加统一(因此更容易理解),并且如果您决定将类更改为继承其他内容,则不太可能中断NSObject.

如果你有一些继承链MyGrandparent > MyParent > MyObject,你都的实施者MyParentMyObject,而MyParent不会覆盖所有MyGrandparent的初始化,那么你可以直接调用一个MyGrandparent"您的S非重写的初始化MyObject初始化.但同样,这是一个坏主意.当您或其他人以后必须重新访问代码时会很困惑,如果您更改以后的实现,可能会中断MyParent.

此外,如果您要创建多个初始值设定项,则需要在此处此处了解指定的初始值设定项 .选择一个初始化程序作为指定的初始化程序非常重要,并确保所有子类初始化程序直接调用超类的指定初始化程序.否则,您可能最终会创建无限递归.我在这个答案答案中彻底解释了这个问题.

UPDATE

在您的示例中,您可以设置如下指定的初始值设定项:

static CGFloat const kMaximumDimensionNone = 0; // or NAN if 0 is a valid max dimension
static CGSize const kSizeNone = { 0, 0 }; // or NAN, NAN if 0x0 is a valid size

- (id)initWithGraphic:(Graphic *)graphic size:(CGSize)size maximumDimension:(CGFloat)maximumDimension {
    if (self = [super init]) {
        _graphic = graphic;
        if (!CGSizeEqualToSize(size, kSizeNone)) {
            [self configureWithSize:size];
        }
        else if (maximumDimension != kMaximumDimensionNone) {
            // Use if(!isnan(maximumDimension)) instead if you use NAN as the placeholder
            [self configureWithMaximumDimension:maximumDimension];
        }
        else {
            [self configureWithDefaultDimensions];
        }
    }
    return self;
}

- (id)initWithGraphic:(Graphic *)graphic {
    return [self initWithGraphic:graphic size:kSizeNone maximumDimension:kMaximumDimensionNone];
}

- (id)initWithGraphic:(Graphic *)graphic size:(CGSize)size {
    return [self initWithGraphic:graphic size:size maximumDimension:kMaximumDimensionNone];
}

- (id)initWithGraphic:(Graphic *)graphic maximumDimension:(CGFloat)maximumDimension {
    return [self initWithGraphic:graphic size:kSizeNone maximumDimension:kMaximumDimensionNone];
}
Run Code Online (Sandbox Code Playgroud)

您不必在公共头文件中公开指定的初始化程序.您可以添加一个单独的头文件,公开指定的初始化程序,以便导入子类.例如,Apple使用UIGestureRecognizerSubclass.h标题执行此操作,标题声明了ForSubclassEyesOnly类别UIGestureRecognizer.

或者您可以将configureWith...方法公开给您的子类,也许您甚至不需要让它们覆盖初始化器.