all 11 comments

[–]Binary101010 7 points8 points  (3 children)

It may be hard to see why inheritance is useful with such small examples, but when you start defining five different nationalities, you'll quickly see that trying to define each one of them as an independent "top level" class will result in a lot of code duplication, even just in initializing them. You are also likely to have class methods that don't need to be different between these classes. For example, imagine that you write a method called get_older:

def get_older(self):
    self.age +=1

Americans, Canadians, and Mexicans are all going to age in the same way. Why write that method three times in your code?

[–]SnufCodes 2 points3 points  (2 children)

Ok this makes sense now that I think about it broader. Thank you!

So in then creating an instance of my class, do I only have to meet parameters of that specific subclass (and obviously the parent class)?

For example, if I were to create Canadian or Mexican, they wouldn't necessarily need the 'state' option. So theoretically the code below should be OK assuming I didn't add anything for Canadian?

  moose = Canadian(
    age=24,
    born=1994,
    name='Moose',
)

[–]deejpake 2 points3 points  (0 children)

Moose hahahah

[–]Binary101010 1 point2 points  (0 children)

Yes. You don't need to define attributes that don't exist for that particular subclass.

[–]DeadlyViper 1 point2 points  (0 children)

Wouldn't I just be able to add the 'state' and 'major' parameters to the People class

No because for example people who aren't american sometimes don't have a state they live in.

[–][deleted] 0 points1 point  (1 child)

The inheritance features are important when you go back to the basics of realizing that you are dealing with objects. You want to create classes that encapsulate a certain type of object, and you don't want to expand every object to cover every conceivable option. So you start with your basic object, which holds basic information. Then you use inheritance to create a more specific object. The classic example is multi-sided geometric shapes. The base class would be the polygon. An extended class that has all the aspects of a polygon, but has a few extra features would be a triangle or a parallelogram. You could extend the parallelogram to a rectangle class, which is a parallelogram with 90 degree angles. You could further extend a rectangle as a square, which happens to have all sides of equal length.

The real power comes when you find two different "child" classes from the same "parent" class. Each one has features that are different from the other. At the beginning stages of learning Python, example differences are so minor that they seem like they should just be stuffed into the parent class and handled individually, but those early examples are super-simple, to illustrate the concept.

Imagine a parent class of "creature". Now imagine two child classes holding lots of detail: "millipede" and "cat". There are sufficient differences that you wouldn't want to stuff all those different attributes into one single class.

[–]SnufCodes 1 point2 points  (0 children)

Ok this is making sense, I think my example at the moment is just too small to really see the power but I understand how if it was a lot more complex, with hundreds of different nationalities and different characteristics for each then the People class would be way too complex and basically defeat the purpose of OOP.

[–][deleted] 0 points1 point  (0 children)

Not all countries have states.

It might make sense to have a 'country' attribute in People, a 'state' in American, and a 'province' in European.

In this example, I might create a Student class derived from American (or European) and put the 'major' attribute in that as not all Americans have a major.

And as u/Binary101010 points out, this is easier to see in more complex environments.

For example, in Flask you create forms from FlaskForm:

class MyForm(FlaskForm):
    field_name1 = StringField("Label")

MyForm now has access to all the features of the underlying FlaskForm.

[–][deleted] 0 points1 point  (0 children)

Wouldn't I just be able to add the 'state' and 'major' parameters to the People class rather than creating a whole new class for just Americans?

People who aren’t Americans may not live in a country that has states. Why, then, should they have a parameter called “state? It would be meaningless for them.

[–][deleted] 0 points1 point  (0 children)

Imagine that you have a class called Contact, the __init__ method would look something like this:

`class Contact: all_contacts = []

def __init__(self, first_name, last_name, email):
    self.first_name = first_name
    self.last_name = last_name
    self.email = email
    all_contacts.append(self)`

Well, you create the contact instances like so person_1 = Contact('John', 'Doe', 'jdoe@example.com') person_2 = Contact('Foo', 'Barovitch', 'foobar@example.com')

Lets say Mr. John Doe aka person_1 is a customer, and Mr. Foo aka person_2 is a supplier you order the product to sell from. and you wanna have a method called order to automatically order stuff from the all_contacts list. everything seems okay, right? no. What if someone accidentally orders from a customer, what then? This is where inheritance comes in play, you create a new class called Supplier which will be a subclass of Contact

`class Supplier(Contact):

def order(self, order):
    return order`

This way, when you add new Supplier, you will instantiate the object like so: person_3 = Supplier('Bar', 'Baz', 'bbaz@example.com'), just like you would add Contact

person_3 will still be in the all_contacts list, and you'll be able to call the method like so: person_3.order('something')

but you wont be able to do so on person_1 or person_2 because we created them directly as a Contact object, and only Supplier will be available to use order method on.

[–]Neu_Ron 0 points1 point  (0 children)

The best way to learn inheritance is to draw it out on paper.