在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现在比写这篇文章的时间长了几年,我希望现在有一个更清晰,标准的解决方案。
答案 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方法,这是有效的,因为你的对象在初始化时已经被分配了。如果你有要传递的变量,那么将它们传递给任何方法被认为是初始化器。
(编辑:可能需要自己。)