[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Initialize not being called on objects created from literals

Oliver Saunders

5/27/2009 12:26:00 AM

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-....

5 Answers

botp

5/27/2009 4:32:00 AM

0

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"

Robert Klemme

5/27/2009 6:05:00 AM

0

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.rubybestprac...

Rick DeNatale

5/27/2009 12:55:00 PM

0

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.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

Oliver Saunders

5/27/2009 8:08:00 PM

0

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-....

Robert Klemme

5/27/2009 9:56:00 PM

0

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_p...

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/...

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.rubybestprac...