OOP : Trying to design a good class structure
<p>Follow up code snippet review question I posted: <a href="http://codereview.stackexchange.com/questions/143576/oop-designing-class-inheritances">http://codereview.stackexchange.com/questions/143576/oop-designing-class-inheritances</a></p>

<p>This is homework so off the bat I am not asking to do it for me but to clarify for me so that I understand.</p>

<p>Here is what the assignment said about the program I have to write:</p>

<p><strong>Required:</strong>
Write an OO Python Program showing how your sub-classes inherit from the super-class(es) You can have one class (preferred but not a must) or two or more super classes.</p>

<p>What I have to do is write a oo python program showing sub-classing inherited by a class or two or more superclasses. The program has to be about shapes. As an example of what I mean by that is:</p>

<p>Shape: Square</p>

<p>Attributes:</p>

<ul>
<li>length </li>
<li>width</li>
</ul>

<p>Methods:</p>

<ul>
<li>area</li>
<li>perimeter</li>
</ul>

<p>I have more shapes of course but from that I find the common attributes and methods from all the shapes and make superclasses and sup-classes.</p>

<p>My super classes are like: 2dShapes, circles and 3dShapes. My sub-classes are like length and width. My methods are area and perimeter. Note I am rambling at this point. The code snippet below does not show this instead I was thinking about making a superclass for attributes and methods and than sub-classes for the shapes? maybe?</p>

<p>Question: is this a good class structure? Is there a better way to structure the classes here? Here is an example of what I'm thinking about how to do this.</p>

<pre><code>class Shapes(attributes):
    def __init__(self):
        attributes.__init__(self)
        # not sure how to go on to make the attributes like height and length, radius ect. Maybe like this???
    def height(self):
        raise NotImplementedError # again this program is not supose to actually do anything. The program is just for us to understand inheritance with classes and super classes.

class 2dShapes(Shapes):
    class Square(self):
        def height(self):
            # ???
</code></pre>

<p>So at this point I am so confused about where to start. Also I am super new to python so be gentle to me  :p</p>

<pre><code>class Vehicle(object):
    #class variable shared between all instances of objects. 
    number_of_vehicles = 0 

    def __init__(self,length,width,color,wheels):
        self.length = length
        self.width = width
        self.color = color
        self.wheels = wheels
        Vehicle.number_of_vehicles += 1 #increasing class varaible count

    def get_length(self):
        print("I am %d meters long!"%self.length)

    def get_wdith(self):
        print("I am %d meters wide!"%self.width)

    def get_color(self):
        print("My color is %s!"%self.color)

    def get_wheels(self):
        print("I have %d number of wheels"%self.wheels)

    #calling my methods so I don't need to call each of their own
    def get_stats(self):
        self.get_length()
        self.get_wheels()
        self.get_wdith()
        self.get_color()

    def honk(self):
        print("beep beep")

class Car(Vehicle):
    def vroom(self):
        print("Cars go vroom vroom")

class Cooper(Car):
    def drift(self):
        print("Mini Coopers can drift well")

class Airplanes(Vehicle):
    def fly(self):
        print("weeeeee I'm flying")

class Tank(Vehicle):
    #custom init because tanks have guns!~ 
    #taking the gun size and tossing the rest of the arguments to the parent. 
    #if the parent doesn't find a __init__ it will keep going up until one is found or unelss we call it. 
    #Here we made a new __init__ so it doesn't go looking for one, but we call super() which is calling for the 
    #parent's __init__
    def __init__(self,gun_size,*args):
        self.gun_size = gun_size
        super(Tank,self).__init__(*args)
    def fire(self):
        print("pew pew pew")

    #I have my custom get_stats but still calls parent's one so I don't repeat code.
    def get_stats(self):
        print("my gun is this big: %d " %self.gun_size)
        super(Tank,self).get_stats()

a = Cooper(150,150,"blue",4)
a.drift()
a.vroom()
a.honk()
a.get_stats()
print(a.number_of_vehicles)

b = Airplanes(200,150,"white",2)
b.fly()
print(b.number_of_vehicles)

c = Tank(500,500,250,"Green",18)
c.fire()
print(c.number_of_vehicles)
c.get_stats()
</code></pre>

<p>Outputs:</p>

<pre><code>Mini Coopers can drift well
Cars go vroom vroom
beep beep
I am 150 meters long!
I have 4 number of wheels
I am 150 meters wide!
My color is blue!
1                     #vehicle count
weeeeee I'm flying    # start of plan section
2                     #vehicle count
pew pew pew           #start of tank section
3                     #vehicle count
my gun is this big: 500  
I am 500 meters long!
I have 18 number of wheels
I am 250 meters wide!
My color is Green!
</code></pre>

<p>So the point of this post was to show you relationship of inheritance. </p>

<p>We have a base class called <code>Vehicle</code> which is a sub class of <code>object</code>. Don't worry about <code>object</code> if you want you can read up on it. </p>

<p>Vehicle class has some attibutes that all vehicles would have, length, width, color, wheels. It also have a class variable called <code>number_of_vehicles</code> which keeps track of how many object instances Vehicle has, basically how many Vehicles we "made". We also have some class methods, that access and uses the attributes we defined in <code>__init__</code>. You can do math on them and what not but for now we are just using them as print statements to show they work. We have a special class method that calls other methods in the same class. So <code>get_stats</code> calls the other <code>get_x</code> methods in the instance. This allows me to call those 4 methods with just "one" method call from my object, see <code>a.get_stats()</code>. We can still call the other methods on it's own like <code>get_color</code>. </p>

<p>We have a sub class called Car which is a vehicle, so we inherit it. Only cars can go vroom, but all cars can go vroom so we have a vroom method only at the car level. The trick is to think what does this class have that is unique to only instances of this class, and if not, can I put it in the parent's class. All vehicles have wheels and so on, but not all vehicles can go vroom (for this example only). </p>

<p>We have a sub class of Car, the cooper (mini cooper), which only it can drift (once again for this example only in real life the drift method would go in vehicle cause all vehicles can draft but bare with me). So this cooper is the only car that can drift so it's down here instead of in the Car class.</p>

<p>Tank's sub class is interesting. Here we have the basic of a vehicle but we have something new, a gun! So our vehicle class can't handle a gun, so we have to make a new <code>__init__</code> method. We assign the object variable <code>gun_size</code> and then pass the rest of the tank's attribute to Vehicle's <code>__init__</code> since the rest of the attributes are the same as Vehicle. We call <code>super(Tank,self).__init__(*args)</code> which is basically saying, I am a tank, this is me, please handle the rest of my attribute, parent of mine. Since tanks have a special attribute of a gun, we have to modify our <code>get_stats</code> method, to deal with the <code>gun_size</code> attribute, but the rest of the stats on the tank are the same as vehicle, so we just call our parents to handle the rest after we deal with our gun. </p>

<p>Now I know this is a very silly example, but I do hope you find some useful information in here. There are other majors points I haven't touched upon but this is a starting point. So back to your original question. Think abstract, the highest level would be a shape, then Rectangles are a type of shape so they would inherit it. Squares are special rectangles, so they would inherit rectangles and so on. </p>

<p>If you have questions don't hesitate to ask. </p>

python python-3.x oop inheritance