Calling another superclass initialization method from a custom initializer in MacRuby
In Objective C, a custom init method must invoke the initializer assigned by the superclass. Consider the following custom initialization method for an NSView substring:
- (void)initWithFrame:(CGRect)aFrame andName:(NSString *)aName {
if(self = [super initWithFrame:aFrame]){
//set up object
}
}
However, MacRuby only offers a keyword super
that just tries to call the same method on the superclass. However, since this is a custom initializer, the superclass does not have such a method.
What is the standard way to deal with this question? I asked this question: MacRuby custom initializers , but I can't say that I understand the answer well and it doesn't seem like some widely accepted solution. Since MacRuby is now several years older than when this post was written, I hope there is now a clearer standard solution.
source to share
In rubymotion (and I think MacRuby shares this behavior) there are two types of classes: pure Ruby, which are used initialize
, and classes derived from the objective-c class. Better not to mix them. If you subclass the objective-c class you should use the init
. your method initialize
will never be called!
This is because the method NSObject##new
is called init
, not initialize
(actually even this is a simplification, but an abstraction works).
your example above is confusing because you are calling init
instead initWithFrame
. You MUST name the designated initializer of the parent class - in which case use super
.
If the initializer you are calling (in this case init
) calls your initializer, you are using the wrong one — in that case, the recursion loop transition does not occur.
Thus, you cannot choose exactly which method to call on the parent. However, you can use your own init method:
def initWithTitle(title)
initWithFrame(CGRectZero)
@title = title
return self
end
I would write this method like this:
def initWithTitle(title)
initWithFrame(CGRectZero).tap do
@title = title
end # that way I never forget to return self
end
source to share
If you read it right, you want to create your own init method in rubymotion, but still call the original init method.
I often do something like this:
#custom initializer
def initialize
self.init # <--calls 'init' from parent
#stuff happens here
end
Instead of calling super, just call the init method, it works because your object is already allocated by the time it reaches initialization. And if you have variables to pass, then pass them to what ever method is considered an initializer.
(Edit: maybe needed it myself).
source to share