Re: [MacRuby-devel] How do I subclass Obj-C classes in MacRuby?
From: Thibault Martin-Lagardette <thibault.ml@gmail.com>
What you can do is a "factory" just like this:
...
You can also do a more Cocoa-ish way:
...
Hope that helps!
yep, that all works... I'd rather be doing it in a more Ruby-ish way though... :) Is the fact that the Ruby-standard initialize method is not called for Ruby classes descended from Obj-C classes expected? To me, at least, it violates the principle of least surprise... for example, in ruby 1.9.1 we see initialize being called russm@worcestershire:~$ irb1.9.1 irb(main):001:0> class C2 < String irb(main):002:1> attr_accessor :foo irb(main):003:1> def initialize foo = "default2" irb(main):004:2> @foo = foo irb(main):005:2> STDERR.puts "setting #{foo}" irb(main):006:2> end irb(main):007:1> end => nil irb(main):008:0> c2 = C2.new setting default2 => "" irb(main):009:0> but not in macruby 0.6 russm@alcazar:~$ macirb irb(main):001:0> class C2 < String irb(main):002:1> attr_accessor :foo irb(main):003:1> def initialize foo = "default2" irb(main):004:2> @foo = foo irb(main):005:2> STDERR.puts "setting #{foo}" irb(main):006:2> end irb(main):007:1> end => nil irb(main):008:0> c2 = C2.new => "" irb(main):009:0>
Glad it works :-) The reason why your example doesn't work is because in MacRuby, String descends from NSString, which is a Foundation object. Foundation objects use "init" and not "initalize", and for syntaxic sugar reasons, #new is aliased to [[obj alloc] init] on Foundation objects :-). $> macirb --simple-prompt
class A < String def initialize super puts "initialize" end def init if super puts "init" self end end end => nil A.new init => ""
On non-Foundation objects, #new behaves as you expect (the ruby way) $> macirb --simple-prompt
class A < Range def initialize(a, b) super puts "range initialize!" end end => nil A.new(1, 2) range initialize! => 1..2
I agree this difference can be confusing, and I think it could find its place in a certain book *stares at Matt* -- Thibault Martin-Lagardette On May 6, 2010, at 20:51, russell muetzelfeldt wrote:
From: Thibault Martin-Lagardette <thibault.ml@gmail.com>
What you can do is a "factory" just like this:
...
You can also do a more Cocoa-ish way:
...
Hope that helps!
yep, that all works... I'd rather be doing it in a more Ruby-ish way though... :)
Is the fact that the Ruby-standard initialize method is not called for Ruby classes descended from Obj-C classes expected? To me, at least, it violates the principle of least surprise...
for example, in ruby 1.9.1 we see initialize being called
russm@worcestershire:~$ irb1.9.1 irb(main):001:0> class C2 < String irb(main):002:1> attr_accessor :foo irb(main):003:1> def initialize foo = "default2" irb(main):004:2> @foo = foo irb(main):005:2> STDERR.puts "setting #{foo}" irb(main):006:2> end irb(main):007:1> end => nil irb(main):008:0> c2 = C2.new setting default2 => "" irb(main):009:0>
but not in macruby 0.6
russm@alcazar:~$ macirb irb(main):001:0> class C2 < String irb(main):002:1> attr_accessor :foo irb(main):003:1> def initialize foo = "default2" irb(main):004:2> @foo = foo irb(main):005:2> STDERR.puts "setting #{foo}" irb(main):006:2> end irb(main):007:1> end => nil irb(main):008:0> c2 = C2.new => "" irb(main):009:0>
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
On 07/05/2010, at 2:17 PM, Thibault Martin-Lagardette wrote:
Glad it works :-)
The reason why your example doesn't work is because in MacRuby, String descends from NSString, which is a Foundation object. Foundation objects use "init" and not "initalize", and for syntaxic sugar reasons, #new is aliased to [[obj alloc] init] on Foundation objects :-).
oh, I understand the implementation detail, I just think it's wrong for a Ruby implementation to behave that way - this isn't just a matter of extending Ruby syntax to support access to Obj-C but rather a change that can break existing Ruby code... what I would expect in this case is for the class I've written in ruby to have initialize called like all other classes written in ruby, and leave it to me to correctly call the designated initializer of my superclass, which I know is -init because I'm subclassing Obj-C code...
On non-Foundation objects, #new behaves as you expect (the ruby way)
yeah, and with things like my OpenDirectory wrapper I can live with it... but when the behaviour of subclassing standard Ruby types differs between the reference implementation and MacRuby I'd be calling that a bug in MacRuby...
I agree this difference can be confusing, and I think it could find its place in a certain book *stares at Matt*
it doesn't need documenting, it needs fixing... :) I guess it all depends whether you're looking at MacRuby as a new language for writing Cocoa applications, or as a runtime for Ruby applications on OSX...
The reason #new currently behaves this way is to work for every object, wether it's Ruby or Cocoa. For #new to work like you expect (which I agree totally makes sense), instead of having #new aliasing [[obj alloc] init], we could alias it to [[obj alloc] initialize], and have -initialize redirect to -init on Foundation objects. I don't know how expected that would be, or if it has any drawback... Laurent, what's your take on that? -- Thibault Martin-Lagardette On May 6, 2010, at 22:09, russell muetzelfeldt wrote:
On 07/05/2010, at 2:17 PM, Thibault Martin-Lagardette wrote:
Glad it works :-)
The reason why your example doesn't work is because in MacRuby, String descends from NSString, which is a Foundation object. Foundation objects use "init" and not "initalize", and for syntaxic sugar reasons, #new is aliased to [[obj alloc] init] on Foundation objects :-).
oh, I understand the implementation detail, I just think it's wrong for a Ruby implementation to behave that way - this isn't just a matter of extending Ruby syntax to support access to Obj-C but rather a change that can break existing Ruby code...
what I would expect in this case is for the class I've written in ruby to have initialize called like all other classes written in ruby, and leave it to me to correctly call the designated initializer of my superclass, which I know is -init because I'm subclassing Obj-C code...
On non-Foundation objects, #new behaves as you expect (the ruby way)
yeah, and with things like my OpenDirectory wrapper I can live with it... but when the behaviour of subclassing standard Ruby types differs between the reference implementation and MacRuby I'd be calling that a bug in MacRuby...
I agree this difference can be confusing, and I think it could find its place in a certain book *stares at Matt*
it doesn't need documenting, it needs fixing... :)
I guess it all depends whether you're looking at MacRuby as a new language for writing Cocoa applications, or as a runtime for Ruby applications on OSX...
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
On 07/05/2010, at 4:01 PM, Thibault Martin-Lagardette wrote:
The reason #new currently behaves this way is to work for every object, wether it's Ruby or Cocoa. For #new to work like you expect (which I agree totally makes sense), instead of having #new aliasing [[obj alloc] init], we could alias it to [[obj alloc] initialize], and have -initialize redirect to -init on Foundation objects. I don't know how expected that would be, or if it has any drawback...
perhaps I sounded a bit cranky in my last mail, if so my apologies... you've pointed me to a perfectly viable workaround for my use case (thanks!), and macruby is still in development so I'll lay off the whinging that things aren't 100%... :) cheers Russell
participants (2)
-
russell muetzelfeldt
-
Thibault Martin-Lagardette