"Marcus Goldfish" <magoldf...@gmail.com> wrote

I'm trying to design a base class for a hierarchy. The properties I want to specify for the base class depend on the values of other properties of the
base class.

Don't worry so much about the properties, the important thing to focus on in your base classes is the behaviour. What exactly will these classes do?
What methods will they have? How will they be overridden in your
subclasses.

Ideally the properties are invisible to the users of the class so the
interactions of the properties should all be controlled by the
methods.

class FoodProcessor:
   "Model for a kitchen appliance food processor"
   speed_settings     # example [1, 2, 3, 4]
   blade_settings      # example ["slice", "grate", "grind"]
   slice_thickness     # example ["thin", "thick"], but only if
blade_setting is "slice"

it only make sense to have the slice_thickness property set when
blade_settings = "slice"; otherwise, it would be preferable to only define
the speed_settings and blade_settings properties.  For example:

So create a method to initialise slicing which sets both properties
(with appropriate default values if you like)

Similarly define methods for grating and grinding. Think about
what you want to *do* with a class not what you want to store.
The function should dictate the attributes.

class ProcessorA(FoodProcessor):
   "A slicing-only processor"
   speed_settings = [1, 2, 3, 4]
   blade_settings = "slice"
   slice_thickness = ["thin", "thick"]

class ProcessorB(FoodProcessor):
   "A non-slicing processor"
   speed_settings = [1,2,3,4]
   blade_settings = ["grate", "grind"]
   slice_thickness = None

Unless this is a multi function food processor I'd probably
go for a heirarchy of

FoodProcessor
   Slicer
   Grater
   Grinder

In fact I might do that anyway and then create
MultiFunction as a subclass of of all 3 food
processors...

class MultiFunction(Slicer, Grater, Grinder):
  etc...

Remember that ideally nothing outside the class should be manipulating
the attributes directly, everything should be done by sending messages
(ie calling methods) to the objects. The fact that you want a heirarchy
suggests that you have some form of polymorphic operations to be
performed? What are those operations at the abstract FoodProcessor
level?

It is actually very common that the root object in a heirarchy has very few if any attributes but will have all the methods needed for the concept
to work. As you subclass you add attributes to support the subclass
specific implementation of the methods.

If you truly want a multi purpose mixer and don't want to subclass from
all 3 types then you could have a changeBlade method that specifies
the blade type and any additional attributes. The Blades could even
be a class heirarchy in their own right:

Blade
   Slicer
   Grinder
   Grater

# create a new processor with initially a slicer blade
p = FoodProcessor(Slicer(thickness))
p..process(spam)
p.changeBlade(Grater(granularity))
p.process(Cheese(5, 'oz')) # uses a Cheese object with weight in ounces...

and so on...

But the only real solution will depend on what you intend to do with
your classes. Think about how you want to write the client code.
Think about doing that using method calls rather than manipulating
the inner data. That way you can leverage polymorphism to your
advantage.

HTH,

--
Alan Gauld
Author of the Learn to Program web site
http://www.freenetpages.co.uk/hp/alan.gauld

_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to