On Thu, Dec 22, 2011 at 1:21 AM, Spencer Pearson <speeze.pear...@gmail.com> wrote: > I see a problem with this, though. The intersection of two lines is > (usually) an object of type Point. Since DrawableLine inherits from > Line, this means that unless I redefine the "intersect" method in > DrawableLine, the intersection of two DrawableLines will be a Point > object, not a DrawablePoint. I don't want to saddle the user with the > burden of converting every method output into its corresponding > Drawable subclass, and I don't want to redefine every method to return > an instance of said subclass. I see no other options if I continue > down the subclassing path. Am I missing something?
You could solve this with a factory. Instead of having Line.intersection() create a Point directly, have it call self.factory.create_point(). In the drawing module, replace the factory for the subclasses with one that creates drawable classes instead. > Option 2. A "draw" function, with a function dictionary. > This feels weird, but is fairly simple to write, use, and extend. We > have a module with a "draw_functions" dictionary that maps types onto > functions, and a "draw" function that just looks up the proper type in > the dictionary and calls the corresponding function. If you create > your own object, you can just add a new entry to the dictionary. The > implementation is simple enough to outline here: This will also work, but inheritance complicates things a little. Do you do a type equality check or an isinstance() check when looking up the type in the dictionary? If the former, then somebody who subclasses geometry.Line to create a GroovyLine subclass must add an entry for GroovyLine to the dictionary, even if the drawing code is the same. The drawing code is not inherited. But if you do an isinstance() check, then you need to be very careful about how you check it. If somebody creates a WavyLine subclass and registers a different drawing method, then you need to make sure the isinstance() check for the WavyLine implementation happens before the regular Line implementation, or the wrong drawing code may get invoked for WavyLine. Probably the easiest way to do this correctly is to follow the MRO that Python has conveniently already built for you. Something like: def draw(x, *args, **kwargs ): for class_ in type(x).__mro__: if class_ in draw_functions: draw_functions[class_](*args, **kwargs) break else: raise TypeError("don't know how to draw things of type " "{0}".format(type(x))) Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list