On Fri, 30 Aug 2002, Gavin Sinclair wrote: > > class LogLine > > attr_reader :month, :day, :hour, :minute, :second, > > :host, :program, :pid, :message > > [...] > > end > > I'd use a Time object instead of :month, :day, etc. of course > > But from there, I have two questions: > > > > 1) Is it possible (or even sensible) to override LogLine.new so that it > > returns an instance of the appropriate subclass? I've never liked the > > Java-style LogLine.getInstance(args); it seems unfair to make > > programmers keep track of whether you're using a Factory internally or > > not. > > There's no such method as LogLine.new, I'm afraid. When you define the > class LogLine, you are creating a constant called LogLine which is of type > class. When you call LogLine.new, it is the new method in class Class > that you are calling. It, of course, calls LogLine.init, and the rest is ^^^^ialize > history. He can add a singleton method def LogLine.new(logline_string) # return subclass instance if apropriate # if not, create a plain LogLine: super(logline_string) end > So creating a (static) method LogLine.create or something like that is > probably the way to go. This is better than overiding new because programmers expect SomeClass.new.class == SomeClass > > The obvious OO way seems to be that each subclass would, on loading, > > register itself with LogLine. Sounds sensible. Just add to your logline class: class LogLine @@subclasses = [LogLine] def LogLine.inherited(subclass) @@subclasses << subclass end def LogLine.create(logline_string) # parse the date ratings = @@subclasses.collect{|subclass| subclass.rate(string_after_date) } best_subclass = @@subclasses[ratings.index(ratings.max)] best_subclass.new(date, string_after_date) end end and implement the classmethod rate for LogLine and all its subclasses to return a number that indicates the likelyhood that it is responsible for this logline. All classes that inherit from LogLine will automatically be added to the class variable @@subclasses. > > Really, the parsed data is best represented as a LogLine, no? > > So it > > would make sense to instantiate a LogLine with the base data, and then > > pass that to the subclasses. But when instantiating the subclass, the > > subclass has to copy over all the data and throw out the copy of the > > superclass, which seems a little wasteful. You want a "become" method: d = LogLine.new(...) old_id = d.id puts d.class => LogLine d.become(LogLine_Subclass) puts d.class => LogLine_Subclass puts (d.id == old_id) => true To my knowledge, ruby does not have this functionality. I'd like to be proven wrong on this. Maybe its possible to implement this in a C extension that does some tricks with ruby's object representation? > conclusion that you're on the wrong track. No. Apart from wanting to use the new method, his aproach looks fairly sensible to me. He presented refreshing ideas and showed that he understands OO programming fairly well. He's just a newby to the ruby and needs help in mapping his ideas to the language. > Basically, I think you should put all the logic of what subclass best > represents the line into LogLine, like: The logic of the subclass should be part of the subclass. Or => maintainance nightmare. > It may be a bit awkward for the client of LogLine to know what to do with > the return value - it'll probably have to type-check it Why? It is_a LogLine, that's for sure. The client got what it asked for. Tobias