![]() |
Initialize not being called on objects created from literals
Initialize doesn't appear to get called.
class Object def initialize @foo = 'bar' end attr_reader :foo end a = Object.new # => #<Object:0x54c964 @foo="bar"> a.foo # => "bar" 'string'.foo # => nil //.foo # => nil I want to have //.foo and 'string.foo give me "bar" as they should. How can I do that? -- Posted via http://www.ruby-forum.com/. |
Re: Initialize not being called on objects created from literals
On Wed, May 27, 2009 at 8:26 AM, Oliver Saunders
<oliver.saunders@gmail.com> wrote: > Initialize doesn't appear to get called. > > class Object > =A0def initialize > =A0 =A0@foo =3D 'bar' > =A0end > =A0attr_reader :foo > end > > a =3D Object.new # =3D> #<Object:0x54c964 @foo=3D"bar"> see relation bw initialize and new > a.foo # =3D> "bar" > 'string'.foo # =3D> nil > //.foo # =3D> nil > > I want to have //.foo and 'string.foo give me "bar" as they should. How > can I do that? try defining a method, eg >> class Object >> def foo >> "bar" >> end >> end =3D> nil >> 1.foo =3D> "bar" >> //.foo =3D> "bar" |
Re: Initialize not being called on objects created from literals
On 27.05.2009 02:26, Oliver Saunders wrote:
> Initialize doesn't appear to get called. > > class Object > def initialize > @foo = 'bar' > end > attr_reader :foo > end > > a = Object.new # => #<Object:0x54c964 @foo="bar"> > a.foo # => "bar" > 'string'.foo # => nil > //.foo # => nil > > I want to have //.foo and 'string.foo give me "bar" as they should. How > can I do that? A class needs to explicitly invoke #initialize of the super class. I guess, since Object does not have any members by default String will not do the invocation. class A def initialize puts "A" end end class B < A def initialize super # or super() in this case puts "B" end end Having said that, it's generally not a too good idea to mess with built in classes - even though you can. But you may produce unwanted side effects. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/ |
Re: Initialize not being called on objects created from literals
On Wed, May 27, 2009 at 2:10 AM, Robert Klemme
<shortcutter@googlemail.com> wrote: > On 27.05.2009 02:26, Oliver Saunders wrote: >> >> Initialize doesn't appear to get called. >> >> class Object >> =A0def initialize >> =A0 =A0@foo =3D 'bar' >> =A0end >> =A0attr_reader :foo >> end >> >> a =3D Object.new # =3D> #<Object:0x54c964 @foo=3D"bar"> >> a.foo # =3D> "bar" >> 'string'.foo # =3D> nil >> //.foo # =3D> nil >> >> I want to have //.foo and 'string.foo give me "bar" as they should. How >> can I do that? > > A class needs to explicitly invoke #initialize of the super class. =A0I g= uess, > since Object does not have any members by default String will not do the > invocation. This is true, see below > > class A > =A0def initialize > =A0 =A0puts "A" > =A0end > end > > class B < A > =A0def initialize > =A0 =A0super > =A0 =A0# or super() in this case > =A0 =A0puts "B" > =A0end > end > > Having said that, it's generally not a too good idea to mess with built i= n > classes - even though you can. =A0But you may produce unwanted side effec= ts. But that's not the whole story. As the OP suspected, literals are created by the parser without going through the normal initialization route: class Object alias_method :old_initialize, :initialize attr_reader :boo def initialize(*args, &b) # !> redefining Object#initialize may cause infinite loop puts "Object#initialize" old_initialize(*args, &b) @boo =3D "who" end end puts "calling String.new" s1 =3D String.new puts "back" puts "s1.boo is #{s1.boo.inspect}" puts "making String#initialize call super" class String alias_method :old_initialize, :initialize def initialize(*args, &b) super puts "String#initialize" old_initialize(*args, &b) end end puts "calling String.new" s2 =3D String.new puts "s2.boo is #{s2.boo.inspect}" puts "\"abc\".boo is #{"abc".boo.inspect}" Produces the following calling String.new back s1.boo is nil making String#initialize call super calling String.new Object#initialize String#initialize s2.boo is "who" "abc".boo is nil untitled:5: warning: redefining Object#initialize may cause infinite loop Note that warning pointing out a potential unwanted side effect. --=20 Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/pers...-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale |
Re: Initialize not being called on objects created from lite
Thanks Rick. I poked around a bit more after the last few posts made
here and couldn't find an answer. I started looking at the Ruby's C code but couldn't really get any useful information from it. Despite this I'm fairly confident what I wanted to do can't be done. But I managed to work around it in the end with a solution that was actually surprisingly simple. For those interested to know what I was doing I was trying to implement a layer for prototype-based OO in Ruby. Didn't really work though. As far as I know (and please correct me if I'm wrong) Ruby doesn't allow you to call a method redefining the meaning of self for the purpose of the call (e.g. apply() in JS) and without this feature you can't really implement this layer in any useful way. -- Posted via http://www.ruby-forum.com/. |
Re: Initialize not being called on objects created from lite
On 27.05.2009 22:08, Oliver Saunders wrote:
> For those interested to know what I was doing I was trying to implement > a layer for prototype-based OO in Ruby. Didn't really work though. Please correct me if I am wrong, but you seem to mean http://en.wikipedia.org/wiki/Prototy...ed_programming Would this approximate what you're after? prototype = Object.new class <<prototype def foo printf "%p %p\n", self, self.class end end o1 = prototype.clone o2 = prototype.clone o1.foo o2.foo > As > far as I know (and please correct me if I'm wrong) Ruby doesn't allow > you to call a method redefining the meaning of self for the purpose of > the call (e.g. apply() in JS) and without this feature you can't really > implement this layer in any useful way. #instance_eval does exactly that: it temporarily sets self to point to a particular instance. But it seems apply() in JS world is used to do something else http://www.devguru.com/Technologies/...ref/apply.html Basically you would need it to call "super class" methods. A few solutions come to mind. For construction you can do def base o = Object.new class <<o def base_meth end end o end def derived o = base # alt: prototype.clone class <<o def derived_meth end end o end If your search the archives I am pretty sure you'll find something about prototype based OO in Ruby. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/ |
| All times are GMT. The time now is 02:45 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.