About finding subclasses

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

On 4/15/07, Dorren [email protected] 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

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

On 4/15/07, eden li [email protected] 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.” [email protected] 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/

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…

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.” [email protected] 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: