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

时间:2012-10-13 07:04:51

标签: objective-c cocoa-touch cocoa

我在用于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;
}

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

1 个答案:

答案 0 :(得分:6)

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

答案很长......

-[NSObject init]方法为documented to do nothing

  

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

因此理论上你不需要打电话。在实践中最好称之为,因为它使您的代码更加统一(因此更容易理解),并且如果您决定将类更改为继承自{{1 }}

如果您有一些继承链NSObject,并且您是MyGrandparent > MyParent > MyObjectMyParent的实施者,MyObject不会覆盖所有MyParent }的初始值设定项,然后您可以直接从MyGrandparent初始值设定项中调用MyGrandparent个未被覆盖的初始值设定项之一。但同样,这是个坏主意。当您或其他人以后必须重新访问代码时会很困惑,如果您稍后更改MyObject的实现,可能会中断。

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

更新

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

MyParent

您不必在公共头文件中公开指定的初始值设定项。您可以添加一个单独的头文件,公开指定的初始化程序,以便导入子类。例如,Apple使用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]; } 标头执行此操作,该标头在UIGestureRecognizerSubclass.h上声明ForSubclassEyesOnly类别。

或者您可以将UIGestureRecognizer方法公开给您的子类,也许您甚至不需要让它们覆盖初始值设定项。