Knowing which subclass called a superclass class method

Hi All,

If I have class A and class B, and they both inherit from S.
And in S there is a class method called doSomething.

How do I know in S’s doSomething wether it was called like:

A.doSomething

or

B.doSomething

thanks,

Rob

Rob B. wrote:

If I have class A and class B, and they both inherit from S.
 And in S there is a class method called doSomething.

 How do I know in S’s doSomething wether it was called like:

 A.doSomething

 or

 B.doSomething

self will be A or B.

HTH,
Sebastian

self will be A or B.

thanks for the quick reply Sebastian.

I was trying to get the class name into a string.

self.class.to_s

gave me Class

however,

self.to_s

indeed gave me S

regards

Rob

to continue on the same theme, if this is the class:

class S

puts “1” + self

def self.doSomething
    puts "2" + self
end

end

I get:

1 S
2 A

why is there this difference? and is there a way to get A in the first
case?

thanks in advance

Rob

Hi –

On Sun, 15 Jun 2008, Rob B. wrote:

to continue on the same theme, if this is the class:

class S

puts “1” + self

def self.doSomething
puts “2” + self

Do you mean self.name, in both cases?

end

end

I get:

1 S
2 A

I assume that you’ve done:

class A < S
end

A.doSomething # or do_something, using Ruby style naming

and that you didn’t really get magically-inserted spaces :slight_smile:

why is there this difference? and is there a way to get A in the first
case?

The code inside a class definition gets executed when the class
definition is read in. Code at the top level of the definition, like
your puts statement, gets executed right away. Method definitions get
executed in the sense that the methods get defined, but the methods
themselves don’t get executed until they’re called.

So your definition of S does two things:

  • prints out “1” + self.name
  • defines a method, to be called later

If you want to do the puts’ing for a subclass, you could do:

class S
def self.inherited©
c.class_eval { puts “1” + self.name }
end
end

(or just puts “1” + c.name)

David

Hi David,

This time I really made the class :wink:

class S

attr_accessor :my_ivar

def self.inherited(c)
     c.class_eval {
       @my_ivar = self.name
     }

end

def initialize
puts “In S initialize, my_ivar = #{@my_ivar}”
super
end

def self.do_something
puts “In S class-method do_something, my_ivar = #{@my_ivar}”
end

end

and,

require “s”

class B < S

def initialize
super
end

def show_my_ivar

puts "In show_my_ivar " + @my_ivar

end

end

when I do B.do_something, @my_ivar is “B” as it should
but if I do B.new, my_ivar is nil

To solve it I can modify initialize like:

def initialize
@my_ivar = self.class.to_s
puts “In S initialize, my_ivar = #{@my_ivar}”
super
end

and
b = B.new
puts b.show_my_ivar

works properly.

But as this is a simplification, in my real app I need a few lines of
code to set @my_ivar, and I 'd rather not have too much duplicate code.

I guess what I am trying for is to configure a variable, using the
name of the subclass, that is readily available to both class methods
and instance methods.

thanks a lot,

Rob

On 14.06.2008 19:38, Phlip wrote:

Sebastian H. wrote:

Rob B. wrote:

If I have class A and class B, and they both inherit from S.
And in S there is a class method called doSomething.

self will be A or B.

self.class.name will == ‘A’ or ‘B’

No, self.name will be “A” or “B” - self.class.name is “Class”.
Remember, we are talking about a class method.

irb(main):001:0> class Base
irb(main):002:1> def self.x
irb(main):003:2> [self.class.name, self.name]
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> class A<Base;end
=> nil
irb(main):007:0> class B<Base;end
=> nil
irb(main):008:0> A.x
=> [“Class”, “A”]
irb(main):009:0> B.x
=> [“Class”, “B”]
irb(main):010:0>

I would not use the name but rather self (the class object) itself if I
would want to do some class specific stuff, but:

Tip: Using this information, such as in an ‘if’ statement, leads to bad
design. The purpose of OO programming is polymorphism. A and B should have
derived methods that doSomething calls. That’s the Abstract Template
pattern.

Absolutely agree.

Kind regards

robert