3

在 Objective C 中,自定义的 init 方法必须调用超类的指定初始化程序。考虑以下用于 NSView 子类的自定义 init 方法:

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

然而,MacRuby 只提供了super关键字,它只是尝试在超类中调用相同的方法。然而,由于这是一个自定义初始化程序,超类没有这样的方法。

解决这个问题的标准方法是什么?我确实看到了这个问题:MacRuby custom initializers但我不能说我非常了解答案,它似乎也不是一些被广泛接受的解决方案。由于 MacRuby 现在比那篇文章写的时候早了几年,我希望现在有一个更清晰、标准的解决方案。

4

2 回答 2

4

在 ruby​​motion 中(我认为 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
于 2013-02-02T18:44:31.800 回答
0

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

我经常做这样的事情:

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

 #stuff happens here
end

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

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

于 2013-02-01T19:41:05.587 回答