From: Mark Hubbart Date: 2004-10-06T06:22:46+09:00 Subject: Re: Extending existing classes On Wed, 6 Oct 2004 03:55:12 +0900, Henrik Horneber wrote: > Edgardo Hames wrote: > > > On Wed, 6 Oct 2004 03:29:35 +0900, Henrik Horneber wrote: > > > >>>>- extending String so you can tell it to remove cpp comments /* remove > >>>>me */ > >>> > >>>Extending string with something like remove_cpp_comments seems awkward > >>>to me. In any usecase for this I'd rather have a class CppCode that I > >>>can ask to remove_comments. (Or even better, to give me the source > >>>without comments.) > >>> > >>>So my personal heuristic tells me not to extend in this case. > >> > >>Now, the reason I was immediatly reminded of that remove_cpp_comments > >>example is, that I wrote a small script some time ago, which used > >>exactly this case. First, I implemented remove_cpp_comments in its own > >>class (which was not called CppCode, but had the same intend), but out > >>of curiosity (and because in ruby I can, dang it! :) ) I moved the > >>remove_cpp_comments method to String. Turns out, the method got shorter > >> and somewhat clearer, at least to me. And I could write something like > >> > >>source_code = IO.readlines(file).join("\n") > >>source_code.strip_comments! > >># instead of source_code = CppCode.strip_comments( source_code) > >> > >>.... you get the idea. > >> > >>Even though the code became clearer on that level, I still have to agree > >>with Brian that it is somehow dirty/awkward on a different level to > >>extend String with such a method. > >> > > > > > > I usually try not to do that kind of things. Then, for each new > > lanaguage you are going to support, you should now add a > > remove_#{lang}_comments to String. But then, when reading a given > > source file you could remove comments that are not so in that > > language. > > > > Regards, > > Ed > > In my case there is never going to be a different language to support, > but in general, that is a good reason not to do it. I'd like to get away > from my example and to a little wider discussion of when to extend > existing classes. I could have written my own subclass of String called > CppSource, so I could have written > > source_code = CppSource.new( IO.readlines(file).join("\n") ) > source_code.strip_comments! > > which might actually be a better solution than to put strip_comments! > into String. On the other hand (again stealing from the other thread), > writing > > time_to_restart = TimeNumeric.new(5).hours + TimeNumeric.new(15).minutes > > is just what we would like to avoid. So, as a guideline, should you only > extend an existing class when you use lots of literals in your code? imho, there are two occasions for extending a class: 1. When the added methods are useful for that class in general (ie, String#rot13, Integer#factors) 2. When you're just hacking :) If the data that you are working with is sort of an extended version of the class, that's when I would subclass. I think the common text markup modules are excellent examples of this; redcloth and bluecloth both act just like strings, but the have a few important methods that treat them as specific data types. In this vein, TimeNumeric might be subclassed to use like this: # TimeNumeric < Float ... where the float value is the number of seconds. time_to_shutdown = TimeNumeric.new(5*60*60 + 15*60) or better yet: time_to_shutdown = TimeNumeric.hours(5.25) or even: time_to_shutdown = TimeNumeric["5:15:00"] # calls "#to_time_numeric" on the string cheers, Mark