Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Inheritance problem
#11
(May-05-2020, 05:46 PM)DPaul Wrote: but i don't see a "generic" superclass here with the different formula's for volume etc
I agree it's difficult to come with common methods in this case.
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#12
Lets say you are writing some sort of geometry learning program. You program can draw a shape and provide a way for the user to change the parameters. It displays characteristics of the shape, or maybe askes a quiz. Your create a base class for all the geometric shapes

As an example:
class Shapes:
    def __init__(self):
        self.name = None
        self.params = None
        self.volume_equation = None
        self.area_equation = None

    def draw(self, rotation):
        """Abstract method for drawing shape on screen"""
        raise NotImplementedError('Subclass responsibility')

    def volume(self):
        """Calculate volume of shape"""
        raise NotImplementedError('Subclass responsibility')

    def surface_area(self):
        """Calculate surface area of shape"""
        raise NotImplementedError('Subclass responsibility')

class Cube(shape):
    def __init__(self, side):
        super().__init__(self)
        
        self.name = 'Cube'
        self.params = {'Side': side}
        self.volume_equation = 'Side^3'
        self.area_equation = '6 * Side^2'

    def draw(self, rotation):
        """Draw shape"""
        # Cube drawing code would go here

    def volume(self):
        """Calculate volume of cube"""
        return self.params['Side']**3

    def surface_area(self):
        """Calculate surface area of shape"""
        return 6 * self.params['Side']**2


class RectangularPrism(shape):
    def __init__(self, l, w, h):
        super().__init__(self)
        self.name = 'Rectangular Prism'
        self.params = {'Length': l, 'Width': w, 'Height':h}
        self.volume_equation = 'Length * Width * Height'
        self.area_equation = '2 * (Length * Width + Length * Height + Width * Height'

    def draw(self, rotation):
        """Draw shape"""
        # Rectangular prism drawing code would go here

    def volume(self):
        """Calculate volume of cube"""
        return self.params['Length'] * self.params['Width'] * self.params['Height']

    def surface_area(self):
        """Calculate surface area of shape"""
        return 2 * (self.params['Length'] * self.params['Width'] + \
                    self.params['Length'] * self.params['Height'] + \
                    self.params['Width'] * self.params['Height'])
                    

class Geometry3D:
    """Program for exploring 3D geometric shapes"""
shapes = [Cube(5), RectangularPrism(5, 5, 5)]

    def select_shape(self)
        """Print list of shapes.  Get user selection"""
        for i, shape in enumerate(shapes):
            print(i, shape.name
        return shapes[int(input('Select a shape: '))]

    def display_shape(self, shape):
        """Display a shape"""
        print(shape.name)
        shape.draw(rotation)
        print('Volume =', shape.volume_equation)
        print('Area = ', shape.area_equation)

    def edit_shape(shape)
        print('Area = ', shape.area_equation)
        for key in shape.params:
            shape.params[key] = float(input(key + ':'))
        self.display_shape(shape)
The idea is that the program knows very little about shapes. Each shape subclass knows how to do all the stuff specific to that shape, and the main application only has to know the attributes common to all shapes. It should be fairly easy to add new features to the program because you don't have to write special code for each shape. If I want to tumble the shape or make it spin the application only has to calculate a location and rotation. The shapes each know how to draw themselves. If I want to add a new shape all I have to do is write a shape class and add the shape to the shape list. Since none of the application is shape dependent, no other code would have to change.

Like nearly all design paradigms, Object Oriented Programming is a tool for managing complexity of large software systems. Done well it can yield amazing results.
Reply
#13
Thanks for the "hierarchical" ideas, which triggered some out-of-the-box thinking.
I need to reflect on this a little, but my goal is to create
an inheritance construction, that makes some sense, however simple.

So probably, i have been looking at this from the wrong angle.
To make it work, it may be better NOT to do classing by shape.

On the top level we have 2D and 3D shapes (forget the tessaract)
Then we have "volumes", "surfaces ", "circonferences" etc.
Then specific shapes.
Or even ,things that need 1 parameter, 2 or 3.
I have some thinking to do.
Paul
Reply
#14
Some more ideas - 2D, but easy to convert to 3D

from collections import namedtuple
from math import sqrt

Point = namedtuple('Point', 'x, y')

class Shape:
    def __init__(self, points):
        self.points = list(points)

    @staticmethod
    def side(point1, point2):
        return sqrt((point1.x-point2.x) ** 2 + (point1.y-point2.y) ** 2)

    @property
    def circumference(self):
        points2 = self.points[1:]
        points2.append(self.points[0])
        return sum(self.side(point1, point2) for point1, point2 in zip(self.points, points2))

class Triangle(Shape):
    def __init__(self, points):
        super().__init__(points)

    @property
    def surface(self):
        # not implemented yet
        raise NotImplementedError('Triangle.surface is not implemnted yet.')

class Square(Shape):
    def __init__(self, points):
        super().__init__(points)

    @property
    def surface(self):
        side = self.side(*self.points[:2])
        return side * side


p1 = Point(0, 0)
p2 = Point(3, 0)
p3 = Point(4, 0)
p4 = Point(4, 4)
p5 = Point(0, 4)

triangle = Triangle([p1, p2, p5])
square = Square([p1, p3, p4, p5])

print(square.circumference)
print(triangle.circumference)
print(square.side(p1, p3))
print(square.surface)
print(triangle.surface)
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#15
OK, I'll go with a mix of deanhystad and buran's examples.
The only thing is that i don't want to confuse issues,
so introducing decorators, collections and namedtuples and inheritance in one example,
makes it more difficult to explain. On the other hand, that makes it more generic.
Maybe we'll settle for a simple and an advanced example. :-)
Paul
Reply
#16
I am really not sure about the purpose of all this (teaching material?)
Why not settle for something that makes it easier and offers more commonality, instead of shape/geometry thing
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#17
(May-06-2020, 07:46 AM)buran Wrote: Why not settle for something that makes it easier and offers more commonality, instead of shape/geometry thing

Oh, I thought it would be a welcome change from "spam" and "eggs" and "foo" examples. Wink
Paul
Reply
#18
(May-06-2020, 05:30 PM)DPaul Wrote: Oh, I thought it would be a welcome change from "spam" and "eggs" and "foo" examples.
I was thinking more for e.g.
Person -> Employee/Manager or Student/Teacher
Vehicle -> car/track/bike
Publication-> book/newspaper/magazine
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#19
Stubborn as we are, this could be a very simple inheritance case.
The class 'circle', can be used as such (circonf, surface)
Then somebody discovers the formulas for a sphere, and they are not so different from circle.
In order to save time, he inherits from circle and does not have to type the whole formula.
Could this be an acceptable inheritance example? (It seems to give the right answers)
Paul
import math

class circle:
    
    def __init__(self, diameter):
        self.r = diameter / 2
        self.pi = math.pi
         
    def circonf(self):
        cir = 2 * self.pi * self.r
        return cir

    def surface(self):
        sur =  self.pi * (self.r ** 2)
        return sur
# inherits from circle !
from circleclass import circle

class sphere(circle): 
    def __init__(self,diameter):
        circle.__init__(self, diameter)
        self.r = diameter / 2

    def area(self):
        ar = 4 * circle.surface(self)
        return ar
         
    def volume(self):
        vol = 4 / 3  * circle.surface(self) * self.r
        return vol
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Inheritance problem Maryan 0 1,254 Oct-25-2020, 02:39 PM
Last Post: Maryan

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020