Forum: Ruby about finding subclasses

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Dorren (Guest)
on 2007-04-15 10:56
(Received via mailing list)
for a given class, find all subclasses

i found the solution (by pit capitain) at
http://groups.google.com/group/comp.lang.ruby/brow...
, 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
Harold H. (Guest)
on 2007-04-15 12:03
(Received via mailing list)
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/seeingMetacla...

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
Eden L. (Guest)
on 2007-04-15 12:40
(Received via mailing list)
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. ;-)
Dorren (Guest)
on 2007-04-16 02:26
(Received via mailing list)
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
Rick D. (Guest)
on 2007-04-16 22:25
(Received via mailing list)
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/
ChrisKaelin (Guest)
on 2007-04-17 00:10
(Received via mailing list)
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...
This topic is locked and can not be replied to.