From: Daniel Brockman Date: 2005-07-29T12:24:39+09:00 Subject: Re: What's so special about operators, built-in classes and modules? Thank you for keeping up Ara --- I'm enjoying this discussion. :-) "Ara.T.Howard" writes: > On Thu, 28 Jul 2005, Daniel Brockman wrote: > >>> i'd say __all__ code depends on that. otherwise >>> >>> module M >>> def self::new >>> raise >>> end >>> end >>> class C >>> include M >>> end >>> >>> c = C::new >> >> Surely you are not suggesting that all code defines >> singleton ‘new’ methods on modules? What I meant by this was that your claim, "i'd say __all__ code depends on that," was a bit bold. >> Considering that this doesn't work, >> >> class X >> def self.new >> raise >> end >> end >> >> class Y < X >> end >> >> x = X.new >> >> why do you expect your example to work? > > well - you have to actually __use__ the method - i was > pointing to the fact that they are inherited in the case > of subclasses and are not in the case of mixins ;-) Yes, and I was trying to ask you whether or not and *why* you expect such a difference in behavior. (If you didn't expect it, then you agree it is surprising?) > harp:~ > cat a.rb > class X > def self.new > raise > end > end > > class Y < X > def self.new; super; end > end > > x = X.new > > harp:~ > ruby a.rb > a.rb:3:in `new': unhandled exception > from a.rb:11 > > >> I don't get why Y's singleton class inherits from X's, >> while C's *doesn't* inherit from M's. > > because otherwise including module could clobber class > methods which generally include hooks to create instances > like 'new', 'instance', 'parse', etc. But you have already demonstrated that inheriting from a class *can* clobber methods like Class#new. So I don't see the difference. I know *what* happens; just not *why*. class AbstractFoo def self.new raise "nope!" end end class Foo < AbstractFoo end foo = Foo.new # error class Foo def self.new # What do I put here? end end Clearly this problem already exists for class inheritance. > if you replace the set of methods responsible for stamping > out instances you are not 'mixing-in' functionality to > those instances - (No, you are mixing in functionality to the *class*, not the instances, though of course the latter refer to the former.) > but changing what type those will be. there is a > fundemental difference here. You are making a *classic* bifurcation here: Your argument boils down to, "you are changing what type the instances will have, therefore you are not mixing in functionality," when in fact I am doing both. It's like if I were to say that in your example, > class X > def self.new > raise > end > end > > class Y < X > def self.new; super; end > end the Y class is not inheriting from the X class, because it's preventing instances from being created. >> Why are you defining M.new? Do you have actual code that >> does this? > > tons. [...] > > module Command > class Abstract > ... > end > class Load < Abstract > ... > end > class Sub < Abstract > ... > end > class Add < Abstract > ... > end > class Store < Abstract > ... > end > def self::new line > orbit_normal_time, command, register, value = parse line > klass = > case command > when /load/ > Load > when /sub/ > Sub > when /add/ > Add > when /store/ > Store > end > klass::new(orbit_normal_time, register, value) > end > end > > class PayloadActivationMessage < AbstractMessage > include Command > end Okay, thank you. I can see that a lot of similar code probably exists. But the example you've given would not be difficult to fix if module metaclass inheritance were added. Actually, your code seems pretty fishy to me as it is: command = Command.new(foo) command.is_a? Command #=> false I think it would have been a better idea to do this: class Command class Load < Command ... end class Sub < Command ... end class Add < Command ... end class Store < Command ... end def self::new line orbit_normal_time, command, register, value = parse line klass = case command when /load/ Load when /sub/ Sub when /add/ Add when /store/ Store end klass::new(orbit_normal_time, register, value) end end If you change your code in this way, the problem disappears; in other words, your code is no longer an example of where module metaclass inheritance is a problem. It's useful to see actual code that would break, but it would be even more useful to see actual, *non-fishy* code that would break. So could you share any other examples? > changing the notion of super is, be definition, a very > strong form on inheritence. Then it is your opinion that including a module is a "very strong form of inheritence"? > added multiple inheritence semantics for module inclusion > would not be backwards compatibile imho. What are "multiple inheritence semantics"? -- Daniel Brockman