[Tutor] Multiple inheritance - Need clarity

Alan Gauld alan.gauld at yahoo.co.uk
Sat Nov 27 06:03:20 EST 2021


On 27/11/2021 01:51, Manprit Singh wrote:
> Below given is a toy example , that calculates the surface area of a
> cylinder (area of circles on both sides + area of cylinder wall)

One of the problems with OOP is that trying to understand it using
toy examples tends to result in bad OO code and hence unclear
understanding. Themore realistic an example you can come up
with the more likely you are to understand how the code works
and why.

> import math
> class Circle:
>     def __init__(self, radius):
>         self.radius = radius
>     def circle_area(self):
>         return math.pi * self.radius**2
> 
> class Rectangle:
>     def __init__(self, s1, s2):
>         self.side1 = s1
>         self.side2 = s2
>     def rectangle_area(self):
>         return self.side1 * self.side2
> 
> class Cylinder(Circle, Rectangle):

And here is the problem.
Inheritance implies an IS-A relationship.
This code says that Cylinder IS A Circle and at the same
time IS also a Rectangle. ie. That you could insert a
Cylinder instance anywhere that a Circle or Rectangle
was expected.

However a cylinder is not a Circle or a Rectangle,
rather it is *composed* of 2 circles and (arguably)
a rectangle. One of the big problems with inheritance
in general, and especially with Multiple inheritance,
is that it gets abused as a method to reuse code
rather than as a model of the problem domain.
Very often people use inheritance when they should use
composition/delegation.

>     def __init__(self, rad, ht):
>         Circle.__init__(self, rad)
>         Rectangle.__init__(self, 2*math.pi*rad, ht)

But this is where you should use super()
Otherwise you will call the object.init twice. (In
this case, not a problem but it could be in real code.
For example, say the root object maintains a counter
of instances, calling it twice would lead to double
counting). Also, you will make your Cylinder
non-compatible with super() in any derived
Cylinders(such as ColouredCylinder say...)

> Just need to know that the way i have called __init__ of circle & rectangle
> inside the init of Cylinder ok or not ? the way i have used circle_area &
> rectangle_area inside cylinder_surface_area  is correct or not ?

Syntactically correct but stylistically and idiomatically wrong.

And wrong primarily because you are trying to use inheritance
where you should be using composition.

A valid superclass for all of these objects might be Shape which
in turn might be sub-classed into 2DShape and 3DShape. Circle
and rectangle would be sub-classes of 2DShape while Cylinder
would be a subclass of 3DShape.

But I would be the first to agree that OOP is difficult to
grasp without using it on larger projects. Its value is not
always evident in small scale code. But you need small scale
to learn the techniques. So often you have to just work with
it and trust that it will make sense later...

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos




More information about the Tutor mailing list