Why is my singleton method called before the class is initia

Consider:

class BigGuy
def initialize
@favorites = [“a”,“b”,“c”]
end

class << self
def display_favs
class_eval “p @favorites
end
end
end

class LittleGuy < BigGuy
display_favs
end

Why does this display “nil”? I expected the initialize of BigGuy to
occur prior to invoking display_favs. Any other construction I should
be using to get my desire behavior of the constructor of the base class
getting called prior to singleton methods called from the child class?

[email protected] [email protected] wrote:

 end

getting called prior to singleton methods called from the child class?
“Initialize” is called when the class is instantiated (i.e. with new).
You are never instantiating this class, so “initialize” is never called.
m.

On 10/26/06, matt neuburg [email protected] wrote:

 def display_favs

occur prior to invoking display_favs. Any other construction I should
be using to get my desire behavior of the constructor of the base class
getting called prior to singleton methods called from the child class?

“Initialize” is called when the class is instantiated (i.e. with new).
You are never instantiating this class, so “initialize” is never called.

True, but kind of beside the point. The initialize method if and when
it is called will set the instance variable @favorites in a new
INSTANCE of BigGuy.

class BigGuy

class << self
def display_favs
class_eval “p @favorites
end
end
end

This makes display_favs a class method of BigGuy.
In the method display_favs self is the class object BigGuy.

so
class_eval “p @favorites
is the same as
BigGuy.class_eval “p @favorites

which is printing a class instance variable of BigGuy which doesn’t
exist.

And…

class LittleGuy < BigGuy
display_favs
end

inside this class definition, self is LittleGuy so

display_favs

is equivalent to:
LittleGuy.display_favs

which executes
BigGuy::display_favs

by inheritance

which prints the uninitialized class instance variable @favorites.

Note also that the class instance variable @favorite in BigGuy is
different from the clas instance variable @favorite in LittleGuy,
although neither one is initialized.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

I’ll say thanks to both of you. I think I was confused on all
accounts, but the biggest issue is probably that I thought the
@favorites was the same for both classes. I guess I will need to
restructure things then. Basically, I want the base class to provide
some default settings that a child class could override using a class
method. Apparently, I am unclear on the way to do so.

Rick DeNatale [email protected] wrote:

class << self
Why does this display “nil”? I expected the initialize of BigGuy to
occur prior to invoking display_favs. Any other construction I should
be using to get my desire behavior of the constructor of the base class
getting called prior to singleton methods called from the child class?

“Initialize” is called when the class is instantiated (i.e. with new).
You are never instantiating this class, so “initialize” is never called.

True, but kind of beside the point.

Perhaps it’s a matter of pedagogy. What is “the point”? That depends
on where one thinks the OP has ultimately gone wrong. The OP might have
any of several misconceptions (it is hard to be certain); the OP might
not be aware:

(1) that initialize is called at instantiation time.

(2) that a class and an instance of that class are different things.

(3) that the singleton method is a class method.

(4) that the @favorites referred to in the class method is not the
@favorites referred to in “initialize”.

Each of us is trying to teach, so each of us, like a good teacher, made
a guess about where the heart of the OP’s misunderstanding might lie. I
guessed (1), with a little bit of (2) thrown in. You are leaning more
toward (3) and (4). Your guess is reasonable, but my guess is not
unreasonable, especially since the OP explicitly said: “I expected the
initialize … to occur”. I spoke to that issue, showing why that
expectation was wrong. So what I said is hardly “beside the point”.

m.

On Fri, 27 Oct 2006, [email protected] wrote:

I’ll say thanks to both of you. I think I was confused on all
accounts, but the biggest issue is probably that I thought the
@favorites was the same for both classes. I guess I will need to
restructure things then. Basically, I want the base class to provide
some default settings that a child class could override using a class
method. Apparently, I am unclear on the way to do so.

it’s astonishingly hard to do in a generic way. take my word for it,
the
easiest way is to do

 harp:~ > cat a.rb
 require 'rubygems'
 require 'attributes'

 class C
   class << self
     attribute 'a' => 42
   end
 end

 class K < C
 end

 p C.a
 p K.a

 class K
   a 'forty-two'
 end

 p C.a
 p K.a


 harp:~ > ruby a.rb
 42
 42
 42
 "forty-two"

regards.

-a

If you want to do it at the class level instead of the instance level,
it looks like what is done quite a lot in rails

for example in active record :

class Toto<<ActiveRecord::Base
end

would use totos as table name by default (define by AR) but you can
chage it to something else like this :

class Toto<<ActiveRecord::Base
set_table_name “mice”
end

now it will use mice instead of toto

if this is what you are trying to do, have a look at rails
implementation, which relies on rails define_attr_method :
http://railsmanual.org/class/ActiveRecord::Base/define_attr_method

hope this helps

matt neuburg [email protected] wrote:

def BigGuy.make_subclass(what)
end
Okay, scratch that. It’s fatally flawed. Oh, well. m.

[email protected] [email protected] wrote:

Basically, I want the base class to provide
some default settings that a child class could override using a class
method. Apparently, I am unclear on the way to do so.

I guess I’m wondering: does it absolutely have to be a class method?
Could it be an ordinary instance method? In this approach, as you
subclass you get to define an instance method, “setup”, that you know
will be called by the constructor:

class BigGuy
def setup
@favorites = “bluto”
end
def initialize
setup
p @favorites
end
end

class LittleGuy < BigGuy
def setup
@favorites = “popeye”
end
end

BigGuy.new #=> “bluto”
LittleGuy.new #=> “popeye”
BigGuy.new #=> “bluto”
LittleGuy.new #=> “popeye”

If you really do want it to be class-based, perhaps a class method might
generate a subclass, set up the way you want it, from which you derive
further subclasses. I’m not very adept at this sort of thing, but my
first go would be something like this:

class BigGuy
def setup
@favorites = “bluto”
end
def initialize
setup
p @favorites
end
class MiddleGuy < BigGuy
end
def BigGuy.make_subclass(what)
MiddleGuy.class_eval %{
def setup
@favorites = “#{what}”
end
}
return MiddleGuy
end
end

class LittleGuy < BigGuy.make_subclass(‘popeye’)
end

BigGuy.new #=> “bluto”
LittleGuy.new #=> “popeye”
BigGuy.new #=> “bluto”
LittleGuy.new #=> “popeye”

I like the ultimate syntax used to generate LIttleGuy, but I’m not
entirely happy because it assumes that the parameter is a string. But I
got all caught up the “eval” situation and couldn’t think straight any
more after a while… Maybe it was a silly idea. m.

matt neuburg [email protected] wrote:

Okay, scratch that. It’s fatally flawed. Oh, well. m.

Aha! This is better:

class BigGuy
def setup
@favorites = “bluto”
end
def initialize
setup
p @favorites
end
class MiddleGuy < BigGuy
end
def self.make_subclass(what)
p = Proc.new {@favorites = what}
MiddleGuy.send( :define_method, :setup, p )
return MiddleGuy.clone
end
end

class LittleGuy < BigGuy.make_subclass(‘popeye’)
end
class DevilishGuy < BigGuy.make_subclass(666)
end

BigGuy.new #=> “bluto”
LittleGuy.new #=> “popeye”
BigGuy.new #=> “bluto”
DevilishGuy.new #=> 666
LittleGuy.new #=> “popeye”

The Proc handles the problem with eval that I was having before, so any
kind of value can now be passed to make_subclass. The other problem I
was having is that we if called make_subclass twice with different
values, only one of those values was being used; hence the “clone” call.

Perhaps this will give the OP something to build on… Anyway it was fun
to think about.

m.

Jacob F. [email protected] wrote:

end
class BigGuy
Class.new(self) do

LittleGuy = BigGuy.with_favorites(‘popeye’)
DevilishGuy = BigGuy.with_favorites(666)

Then the following code produces the same output as yours above:

BigGuy.new #=> “bluto”
LittleGuy.new #=> “popeye”
BigGuy.new #=> “bluto”
DevilishGuy.new #=> 666
LittleGuy.new #=> “popeye”

Yeah! I could NOT for the life of me figure out how to make that
anonymous class, and the direct assignment just didn’t occur to me.
Thanks - m.

On 10/27/06, matt neuburg [email protected] wrote:

def self.make_subclass(what)
p = Proc.new {@favorites = what}
MiddleGuy.send( :define_method, :setup, p )
return MiddleGuy.clone
end
end

You can do away with the explicit “MiddleGuy” class and the clone
call, by just creating an anonymous class on each invocation:

class BigGuy
def setup
@favorites = “bluto”
end

def initialize
  setup
  p @favorites
end

def self.with_favorites(favorites)
  Class.new(self) do
    define_method(:setup) do
      @favorites = favorites
    end
  end
end

end

And while we’re at it, if the only purpose of the on-the-fly class was
for the subclass to inherit from, why not make the subclass be the
on-the-fly class:

LittleGuy = BigGuy.with_favorites(‘popeye’)
DevilishGuy = BigGuy.with_favorites(666)

Then the following code produces the same output as yours above:

BigGuy.new #=> “bluto”
LittleGuy.new #=> “popeye”
BigGuy.new #=> “bluto”
DevilishGuy.new #=> 666
LittleGuy.new #=> “popeye”

Jacob F.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs