Knowing which subclass called a superclass class method

R

Rob Boellaard

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
 
S

Sebastian Hungerecker

Rob said:
If I have class A and class B, and they both inherit from S.
=C2=A0 And in S there is a class method called doSomething.

=C2=A0 How do I know in S's doSomething wether it was called like:

=C2=A0 A.doSomething

=C2=A0 or

=C2=A0 B.doSomething

self will be A or B.

HTH,
Sebastian
=2D-=20
NP: Dark Suns - Infiltration
Jabber: (e-mail address removed)
ICQ: 205544826
 
P

Phlip

Sebastian said:
Rob Boellaard wrote:
self will be A or B.

self.class.name will == 'A' or 'B'

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

Rob Boellaard

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
 
R

Robert Klemme

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
 
R

Rob Boellaard

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
 
D

David A. Black

Hi --

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 :)
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)
c.class_eval { puts "1" + self.name }
end
end

(or just puts "1" + c.name)


David
 
R

Rob Boellaard

Hi David,

This time I really made the class ;-)


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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top