From: dblack@... Date: 2002-12-12T13:32:43+09:00 Subject: Re: do I really not understand inheritance?? Hi -- On Thu, 12 Dec 2002, Chris Pine wrote: > How am I supposed to get all of the Classes/Modules which some object 'obj' > is a kind_of? Get klass (as above) and call klass.ancestors? To get all of them you'd want to traverse both the singleton class and the non-singleton [do we have a better word than that?] class: class Object # This doesn't save any typing in this example, but # it can come in handy in the long run :-) def singleton_class class << self; self; end end def all_ancestors (singleton_class.ancestors + self.class.ancestors).uniq end end p ENV.all_ancestors # [Enumerable, Object, Kernel] > I guess all of my confusion, and thus my ultimate complaint comes back to > this: > > Why doesn't the 'class' method return the singleton class? Consider this: class A def A.some_method "hi" end end I've defined a singleton method on the object A, which is a Class object. This singleton method is defined (by definition) in A's singleton class. Now, according to what you're suggesting, A would no longer be a Class object, but would be a "class << A; self; end" object. Then let's say we do this: a = A.new Well, A is not a Class any more, but let's assume it still responds to 'new'.... But what do we get from this: a.class We can't get A, because A is no longer a Class! So by simply adding a singleton method to an object, we've tied everything in knots. This example uses the familiar scenario of class methods (i.e., singleton methods added to Class objects), but the lesson is general: the notion of the singleton class is part of a whole design, and can't just be changed or discarded. (I also happen to think it's intensely cool, but I won't push that at the moment :-) > Moreover, check this out: > > class Foo > end > > foo = Foo.new > > klass = class << foo; self; end > > p foo.instance_of? Foo # --> true > p foo.instance_of? klass # --> false > > That doesn't seem right to me at all. (Though it does seem consistent, just > consistently wrong... or at least confusing.) I would say that foo *was* an > instance of Foo, but that changed when you made foo do things other Foo's > couldn't. At that point (when foo got it's own singleton class), foo became > an instance of klass. I think you have to look at the overall design of Ruby, which incorporates these two distinct constructs which have distinct roles. They're not at war. An object has a historical class, which is what it was instantiated as, and it has a private "stash" of individuated behavior which is called its singleton class. Neither of these obliterates the other. Mind you, I don't want to discourage the loosening of the notion of an object's "class". Imagine what would happen to the idea of testing for type: case thing when String ... when Array ... when Thingy ... if adding a singleton method to thing changed its class! However, one thing at a time :-) The design really does make sense. > [...] > ...why not just have the new regular (non-singleton) class created? Is it > such a terrible thing that someone *might* try to instantiate the class?? I'm tempted to say: think of it as a pseudo-class, or something, though I don't want to muddy the waters of terminology. In practical terms, one thing to keep in mind is that nothing is denied you. Ruby offers a full suite of techniques for manipulating objects and their capabilities. The key to this is modules: mixing and matching object capabilities through modules, objects can share exactly the kinds of relations that one envisions with the (paradoxical) "multiple objects of a singleton class" concept. David -- David Alan Black home: dblack@candle.superlink.net work: blackdav@shu.edu Web: http://pirate.shu.edu/~blackdav