Initialize not being called on objects created from literals

Discussion in 'Ruby' started by Oliver Saunders, May 27, 2009.

  1. 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/.
    Oliver Saunders, May 27, 2009
    #1
    1. Advertising

  2. Oliver Saunders

    botp Guest

    On Wed, May 27, 2009 at 8:26 AM, 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">


    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"
    botp, May 27, 2009
    #2
    1. Advertising

  3. 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/
    Robert Klemme, May 27, 2009
    #3
  4. On Wed, May 27, 2009 at 2:10 AM, Robert Klemme
    <> 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 :eek:ld_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 :eek:ld_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/person/9021-rick-denatale
    LinkedIn: http://www.linkedin.com/in/rickdenatale
    Rick DeNatale, May 27, 2009
    #4
  5. 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/.
    Oliver Saunders, May 27, 2009
    #5
  6. 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/Prototype-based_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/ecmascript/quickref/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/
    Robert Klemme, May 27, 2009
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    6
    Views:
    470
    ÈÎÔ¶[΢Èí]
    Sep 22, 2005
  2. John Goche
    Replies:
    8
    Views:
    16,458
  3. jimjim
    Replies:
    12
    Views:
    1,895
    Ron Natalie
    Jun 3, 2005
  4. Felix
    Replies:
    1
    Views:
    337
    Felix
    Sep 29, 2006
  5. Replies:
    1
    Views:
    154
    James Britt
    Nov 24, 2005
Loading...

Share This Page