On Thu, 17 Jun 2004, Florian Weber wrote: > hi! > > i have a design question. for example i have a class which reads a file > and prints out each line with line numbers. what if now i wanna be able > to plugin some functionality which sorts the file, depending on some > conditions (extension, etc) before its passed on to the line numbering > functionality. the class should be as less tied as possible to the > sorting > functionality as possible.. > > how would you normally design that in ruby? > > would you just overwrite the method which calls the file read method > and passes it to the numbering method? > > would you pack an object in between, which would check if the file > has to be sorted, because the conditions are true, read the file and > the return the sorted or unsorted content? > > basically im wondering if its considered a good practice to overwrite > methods on the same class or if its kinda hackish.. =) > > thanks a lot! > > ciao! > florian first i'd separate the notion of a file's lines into it's own class - one that simply loads a file and provides a method to access those lines, but does no printing. then i'd design outputter classes that operate on line sets. somewhere in between you can filter/munge the lines - possible using a class hierarchy of Mungers, possibly using duck-typed objects which respond_to? 'munge', possibly just using callbacks (Procs). this uses the last approach: ~ > cat a.rb class LineSet < Array attr :path def initialize path super() @path = path replace(IO.readlines(path)) end def munge(*procs) c = self.cp unless procs.empty? procs.each{|pc| c = pc.call(c)} else c = yield c end c end def munge!(*procs, &block) replace(munge(*procs, &block)) end def cp Marshal.load(Marshal.dump(self)) end end class Outputter def initialize lines @lines = lines end def output out raise NotImplementedError end end class NumberedOutputter < Outputter def output out = STDOUT @lines.each_with_index do |line, idx| out << "#{ idx }: #{ line }" end end end lines = LineSet.new __FILE__ reverser = lambda{|ls| ls.reverse} shrinker = lambda{|ls| ls[0,2]} puts '----' munged = lines.munge reverser, shrinker no = NumberedOutputter.new munged no.output puts '----' lines.munge! shrinker, reverser no = NumberedOutputter.new lines no.output ~ > ruby a.rb ---- 0: no.output 1: no = NumberedOutputter.new lines ---- 0: attr :path 1: class LineSet < Array -a -- =============================================================================== | EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | A flower falls, even though we love it; and a weed grows, even though we do | not love it. --Dogen ===============================================================================