【问题标题】:Do subclasses ALWAYS need to implement a designated initializer in Objective-C?子类是否总是需要在 Objective-C 中实现指定的初始化程序?
【发布时间】:2011-06-11 10:43:14
【问题描述】:

不需要添加特定类初始化代码的子类是否必须实现超类的指定初始化器?

Apple 的 NSObject 的 init 方法的文档提供了一些讨论:

“每个班级都必须保证 init 方法要么完全返回 类的功能实例或 引发异常。子类应该 覆盖init方法添加 类特定的初始化代码。”

"如果子类进行任何初始化 它自己的,它必须定义自己的 指定的初始化器。这种方法 应该首先发送一条消息到 super 调用指定的 其超类的初始化器。”

但是,当子类不需要额外的初始化代码时,没有指定任何内容。

下面的代码试图澄清我的问题。 ClassA 具有名为 initWithX:Y: 的指定初始化程序。 ClassB 不需要额外的初始化,一切都由 ClassA 提供。

解释代码:

@interface ClassA : NSObject {
  NSInteger x;
  NSInteger y;
}

- (id)initWithX:(NSInteger)initX Y:(NSInteger)initY;

@end

@implementation ClassA 
    
- (id)initWithX:(NSInteger)initX Y:(NSInteger)initY {
  if(self = [super init]) {
    x = initX;
    y = initY;
  }
  return self;
}
@end

@interface ClassB : ClassA {
  //no extra variables
} 

//some extra static methods add to provide some differences 
//  between ClassA and ClassB in sample code
+ (NSInteger)extraMethodOne;
+ (NSInteger)extraMethodTwoWithInteger:(NSInteger)anInteger;

@end

@implementation ClassB

/////////////??QUESTION HERE??///////////////////
//Is the implementation below needed?
//If I call [[ClassB alloc] initWithX:1 Y:2], won't it run the code in ClassA
//  with the self set to whatever [ClassB alloc] is?
/////////////////////////////////////////////////
- (id)initWithX:(NSInteger)initX Y:(NSInteger)initY {
  if(self = [super initWithX:initX Y:initY]) {
    /* Don't need class-specific initialization code */
  }
}

//some extra static methods add to provide some differences 
//  between ClassA and ClassB in sample code
+ (int)extraMethodOne {return 1;}
+ (int)extraMethodTwoWithInteger:(NSInteger)anInteger {return 2 + anInteger;}

@end

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    “但是,当子类不需要额外的初始化代码时,没有指定任何内容。”

    没错——什么也不做。

    当 Apple 说“”If 子类对其自身进行任何初始化......等等等等时,他们的意思是“If 和仅当子类对其自身进行任何初始化...等等等等...否则什么都不做。”

    值得记住:你不会经常构建一个完整的大型子类,它有一个完整的链它自己的初始化程序(指定的初始化程序,以及更多),然后你(或其他)将继承该新子类。 (如果你或其他人确实会继承这个新的子类,那么,是的,那时你必须小心地按照 Apple 上面所说的去做。)

    在实践中,99% 的时间,您只是将 UIView 子类化,并且您将一些代码放入 XCode 自动为您粘贴的“init”框架中。令人难以置信的是,如果有人在那里子类化了我们的子类,他们将不得不弄清楚,等待它,“init”是您子类中指定的初始化器!

    关于 Apple doco。他们做得非常出色,但是,在 doco 中有很多这样的问题的例子。一个很好的例子:Is there a proper way to handle overlapping NSView siblings?。注意说“无意义”的部分

    【讨论】:

    • 感谢您的回答。以后我会记住当且仅当规则的。
    【解决方案2】:

    如果您的新类不需要任何额外的初始化,则您不需要指定的初始化程序。但是,您可能还是想这样做,以防您以后决定更改子类。

    【讨论】:

      【解决方案3】:

      答案就在你的问题中:

      “如果子类自己进行任何初始化,它必须定义自己的指定初始化程序。此方法应首先向 super 发送消息以调用其超类的指定初始化程序。”

      如果您不需要进行任何额外的初始化,则无需覆盖(或创建您自己的)指定初始化程序。 initWithX:Y: 的方法查找将简单地使用超类实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-31
        • 2021-10-11
        • 2012-07-22
        • 2018-04-22
        • 1970-01-01
        相关资源
        最近更新 更多