从MacRuby中的自定义初始化程序调用不同的超类init方法

时间:2013-01-31 01:43:28

标签: objective-c initialization macruby rubymotion

在Objective C中,自定义init方法必须调用超类的指定初始值设定项。考虑以下针对NSView的sublcass的自定义init方法:

- (void)initWithFrame:(CGRect)aFrame andName:(NSString *)aName {
    if(self = [super initWithFrame:aFrame]){
        //set up object
    }
}

但是,MacRuby只提供super关键字,它只是尝试在超类中调用相同的方法。但是,由于这是一个自定义初始值设定项,因此超类没有这样的方法。

解决这个问题的标准方法是什么?我确实看到了这个问题:MacRuby custom initializers但我不能说我理解答案很好,也不是一些广泛接受的解决方案。由于MacRuby现在比写这篇文章的时间长了几年,我希望现在有一个更清晰,标准的解决方案。

2 个答案:

答案 0 :(得分:4)

在rubymotion中(我认为MacRuby分享了这种行为)有两种类型:纯Ruby,使用initialize,类派生自objective-c类。最好不要混淆两者。如果要子类化objective-c类,则应使用init方法。你的initialize方法永远不会被调用!

这是因为NSObject##new方法调用了init,而不是initialize(实际上即使这是过度简化,但抽象也有效)。

上面的示例令人困惑,因为您拨打的是init而不是initWithFrame。您必须调用父类的指定初始值设定项 - 在这种情况下,使用super

如果您调用的初始值设定项(在这种情况下为init,则调用您的初始值设定项,则表示您使用了错误的初始化程序 - 在这种情况下,没有转义递归周期。

因此,您无法准确选择在父级上调用哪种方法。但是,您可以使用自己的init方法:

def initWithTitle(title)
  initWithFrame(CGRectZero)
  @title = title
  return self
end

我会这样写这个方法:

def initWithTitle(title)
  initWithFrame(CGRectZero).tap do
    @title = title
  end  # that way I never forget to return self
end

答案 1 :(得分:0)

如果我理解正确,你想在rubymotion中创建自己的自定义初始化方法,但仍然调用原始的init方法。

我经常做这样的事情:

#custom initializer
def initialize
 self.init # <--calls 'init' from parent

 #stuff happens here
end

不是调用super,只需调用init方法,这是有效的,因为你的对象在初始化时已经被分配了。如果你有要传递的变量,那么将它们传递给任何方法被认为是初始化器。

(编辑:可能需要自己。)

相关问题