About finding subclasses


#1

for a given class, find all subclasses

i found the solution (by pit capitain) at
http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/e812c7cef446a96
, it works, but i don’t understand it.

require “enumerator”

def get_subclasses(klass)
ObjectSpace.enum_for(:each_object, class << klass; self;
end).to_a
end


i don’t understand what “class << klass; self; end” does. can someone
rewrite and make it longer?

Dorren


#2

On 4/15/07, Dorren removed_email_address@domain.invalid wrote:

end).to_a
end


i don’t understand what “class << klass; self; end” does. can someone
rewrite and make it longer?

There are two potentially confusing bits about that very elegant piece
of code.

One is the use of enumerator and enum_for, which can be pretty easily
unrolled. However, it may not be clear from that code that the hard
work is actually being done by ObjectSpace.each_object which accepts a
parameter to use as a ‘filter’

The other confusing bit could be the use of the “class << object”
form, which is described as such (in the pickaxe):

… the class <<obj notation, which basically says “build me a new
class just for object obj.” …

Thats one way of putting it. Another way is presented in this article
(which is the explanation that makes the most sense to me):
http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html

Here is a ‘longer’ version of the above like you asked for, though,
I’m not sure it’s any more clear:
#################################
class Object

The hidden singleton lurks behind everyone

def metaclass
class << self
return self
end
end
end

def get_subclasses(klass)
the_subclasses = []

ObjectSpace.each_object( klass.metaclass ) do |object|
the_subclasses.push object
end

return the_subclasses
end

class A
end

class B < A
end

p get_subclasses( A )
#################################

Hope that helps,
-Harold


#3

Metaclass, that’s new to me.I have to re-read the pick-axe book and
that website, and has a little better understanding now.

Thanks all.

Dorren


#4

On 4/15/07, eden li removed_email_address@domain.invalid wrote:

Dang, you beat me to it. I had typed up a similar response. Here’s a
minor tweak though.

On Apr 15, 4:02 pm, “Harold H.” removed_email_address@domain.invalid wrote:

… the class <<obj notation, which basically says “build me a new
class just for object obj.” …

As far as I can tell, all objects (and thus all classes) already have
this singleton class. “class << klass; self; end” is just a way to
get at it.

Well logically at least. For regular objects a singleton class isn’t
created until it’s needed.

So:

a = “abc”
#at this point there is no singleton class for the instance of String
referenced by a
def a.foo
“foo”
end
#at this point it does, the singleton class was created to hold the
method.

Of course you can’t ever see the lack of a singleton class, at least
from ruby code, in order to do so requires an extension.

Classes get their singleton classes when they are created.


Rick DeNatale

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


#5

Harold H. wrote:

 ObjectSpace.enum_for(:each_object, class << klass; self;

There are two potentially confusing bits about that very elegant piece of code.
class just for object obj." …
def metaclass
the_subclasses.push object

p get_subclasses( A )
#################################

Hope that helps,
-Harold

Wow, why’s just twisted my brain… I will have to read his article
again in a few days, and the maybe again and again until I really may
get it… but now I just need a drink…


#6

Dang, you beat me to it. I had typed up a similar response. Here’s a
minor tweak though.

On Apr 15, 4:02 pm, “Harold H.” removed_email_address@domain.invalid wrote:

… the class <<obj notation, which basically says “build me a new
class just for object obj.” …

As far as I can tell, all objects (and thus all classes) already have
this singleton class. “class << klass; self; end” is just a way to
get at it. why’s article defines Object#metaclass as an easy way to
shorthand this long form syntax.

So, it’s pretty clear from the docs that ObjectSpace#each_object takes
a module/class as a filter and will return only objects which are
subclasses of said module/class. If you hand it a metaclass, it does
simply filters for objects which have metaclasses matching the same
criteria.

class A; end
=> nil

class B < A; end
=> nil

metaclass = class << A; self; end
=> #Class:A

B.kind_of?(metaclass)
=> true

B.new.kind_of?(metaclass)
=> false

So ObjectSpace#each_object will end up returning only classes
subclassed from the given “klass” since #kind_of? will hold true for
only those objects matching that criteria.

I think. :wink: