From: David Masover Date: 2008-06-05T03:19:26+09:00 Subject: Re: Module philosophy On Wednesday 04 June 2008 08:49:48 Leslie Viljoen wrote: > Sorry to beat a dead horse, but to confirm: the only way to mix a > module into an already > existing class it to reopen it with something (ugly) like this: > > class String; include Crc; end > > (1) Is that right? Short answer: You'll have to mess with it dynamically, but that is far from the only syntax to do so. Other obvious ones: String.class_eval { include Crc } String.send :include, Crc And there are always stranger things like: "foo".class.class_eval { include Crc } > And then to mix a module into an instantiated object, you can use > extend, and that > modifies the one object. Yes, but keep in mind: "include"ing a module into a class will affect all existing and future instances of that class, and of any subclasses. So you're probably not going to extend if you include. > (2) Philosophically, is there any reason why > extend can't be used > in the same way on classes? (ie. String.extend(Crc)) As others have said, they do different things -- include adds instance methods to a class, and extend adds methods to an object. It's a tricky concept, but remember that classes are objects, too. So: some_string.extend(Crc) # will define some_string.crc16_ok? String.extend(Crc) # will define String.crc16_ok? So, extend works on the actual object you use it on, and include works on any instances of it. You could do this, for example: Class.send :include, Crc # Now all classes will have a crc16_ok? class method, for example: String.crc16_ok? That's probably not what you want. > ...is that the right way to make this module work properly? Or are > some modules just not suitable for extend? I think that comes down to personal philosophy -- I haven't seen (or used) 'extend' a whole lot. It seems most useful when you'd only want to apply it to a single object, and then, I'd usually use instance_eval instead. On the other hand, including it into String means you're affecting all Strings, and polluting String's method namespace. It means that no one else can define String#get_crc16. The other way would be to use a separate class -- either something which contains both a String and a CRC (as Robert suggested), or something which inherits from String. And either way, depending on how much work you want to do, you could always override all methods on String which return a String, and force them to either return an extended String, or return a CrcString, depending on how you decide to do it.