From: Devin Mullins Date: 2005-07-28T13:14:49+09:00 Subject: Re: What's so special about operators, built-in classes and modules? Yukihiro Matsumoto wrote: >|What would be bad about allowing the include method to take Classes in >|addition to Modules? (And to keep everything else the same, including >|the distinction between subclassing (via "<") and mixin-ing (via >|"include").) > >If we allow "include" to take classes, it's a plain multiple >inheritance. > If that were true, then your previous statement wouldn't be true: "Besides that, there's no diamond inheritance in Mixin inheritance." If we make the include method act the same on Classes as it does on Modules (that is, to call #append_features, which, in turn, adds the constants, methods, and module variables of the included class to the receiving class), then that's just Mixin inheritance on Class objects. > We should stand all the complexity of multiple >inheritance by that. > I don't see "module Enumerable; ... end" as being simpler than "class Enumerable; ... end". Am I missing something? > I might have misunderstood you since I'm not >sure what you meant by "keeping everything else the same". > > Specifically, running include on a Class doesn't modify self.superclass, and the super keyword would still try to talk to the actual superclass, and not anything being mixed in, just like is the case with Modules. Probably other things, too, but my mind is a little fuzzy right now. Granted, weird things would happen if someone tried to include Array, but weird things happen now when someone tries to subclass Array. Allowing Classes to be included would be backward compatible (except for code that actually _intends_ to raise a TypeError), and so your core and std libs would be the same. As such, I don't see the comparison to C++'s wacky IO inheritance graph as valid. Well, even if your mind is set, matz, I appreciate your listening. In all fairness, I /don't/ have a use case waiting in the hangar, should classes and modules one day unify. :) The following is really ugly, and completely untested, but might demonstrate my intent: require 'ruby2ruby' #see http://dark.fhtr.org/ruby2ruby.rb #or http://blog.zenspider.com/archives/2005/02/rubytoruby.html class Module alias_method :orig_include, :include def include(*mods) classes, mods = mods.partition {|m| m.is_a? Class} classes.each {|klass| klass.append_features(self)} orig_include(mods) end end class Class def append_features(mod) constants.each {|const| mod.const_set(const,const_get(const))} class_variables.each do |var| value = eval "@@#{var}" mod.class_eval { @@temp = value } mod.class_eval "@@#{var} = @@temp" end instance_methods.each do |meth| mod.class_eval instance_method(meth).to_ruby end end end I also might be doing things the stupid ways at times. So sue me. Thanks, Devin