9 - Inheritance Question


#1

To me this seems like the lesson for which CodeAcademy has done the worst job preparing us to understand what's going on.

It took me a while to figure out that I had to reinitialize all the values I already initialized in the Car class in the ElectricCar class and include the Car.init(self, model, color, mpg) line. I was expecting the ElectricCar class to inherit these arguments from the Car class and that reinitializing them wouldn't be necessary. So you could initialize ElectricCar with battery_type and it would understand that this argument was to be appended to the existing arguments that exist within the Car class and when you create an ElectricCar you'd be able to pass all the arguments initialized in Car as well as the battery_type. This does not seem to be the case.

So, my question is - does inheritance only pass down methods and variables you've set within it? By that I mean that any arguments you want to pass in during the creation of an object of that class has to be initialized in every child class?

Apologies if I've made terminology mistakes in this post - more than happy to hear any corrections.

For those struggling to get it to work here's my code that CodeAcademy allowed to pass

class Car(object):
    condition = "new"
    def __init__(self, model, color, mpg):
        self.model = model
        self.color = color
        self.mpg   = mpg
    def display_car(self):
        print "This is a %s %s with %s MPG." % (self.color, self.model, str(self.mpg))
    def drive_car(self):
        self.condition = "used"
        
class ElectricCar(Car):
    def __init__(self, model, color, mpg, battery_type):
        Car.__init__(self, model, color, mpg)
        self.battery_type = battery_type

my_car = ElectricCar("Tesla", "blue", 250, "molten salt")

#2

Hello, @pyrunner43701!
That's one good question, I have to say.

Inheritance is used to indicate that one class will get most or all of its features from a parent class so in that case there was no problem overriding the init() function from the parent class (and I don't know why my underscores are not showing up)

The things is: not all instances are the same, each of them might (or even will) have a different feature.
One will have an specific method, other will have more arguments, another one will have less arguments and so on.

If you set the method run() in an class named Animal(), who we'll suppose to be the parent class, the subclasses that will come after, let's suppose they're Dolphin and Dog, will also have access to that same function but it depends on the programmer if he/she will allow a Dolphin to use such method.

Q: Okay but what happens if you want to initialize the object Dolphin and it has different arguments compared with the parent class, Animal?
A: In this case, since you don't have the same arguments from your parent class, considering that are NO similar arguments, you'll need to initialize it, one by one inside of your subclass.

Q:Can I initialize my subclasse calling the init() function from my parent class?
A: Yes, you can. Just super and things will be fine.

But if things are similar, just with one or two arguments that are different, you can simply do like you did:

 def __init__(self, model, color, mpg, battery_type):
        Car.__init__(self, model, color, mpg)
        self.battery_type = battery_type

In this case you're simply overriding it and the fact that the instruction were for you to set the values just like you did with the parent class, Car, is because it's way more simple for someone who never faced OOP and inheritance before to understand it.

Q: Okay so how does the init() calling the parent class works inside of the init() inside the subclass?
A: I believe it's something like this: your program will know which instance you're referring too due to the self argument and that same is also being passed to the init() from the parent class. Due to that, you'll be able to set the values of it, since you're just really using something that was created before, other than doing it again.

Note: The statement above is personal, as well. The first time I've face OOP and Inheritance was in C++ and at first wasn't easy but I got used to it.

I truly hope I was clear but if not, let me know and I'll try to find another way to explain this!


#3

Note: This is more like an extra information post, I think it would be nice to talk about it.

My post was quite big so I decided to write this one as well.
There's something in OOP called Visibility, also known as Encapsulation, and that tells what other classes can do with your methods and variables.

In Python, we don't really have such thing. All attributes and methods are visible for everyone but Python provides "name mangling" to help you hide names in classes.
If you name an attribute or a method with double scores:

def __testFunction(self)

Other functions won't be able to see it and won't use it.
Whenever we do this, Python will change the name of the function to following format: className__functionName.

Here's a screenshot of a test:
Before using name mangling

After using name mangling

Trying to access the method that's no longer hidden with a subclass

Trying to access the method that's 'hidden' with a subclass


#4

pyrunner43701, thanks for this question. I opened Q&A with precisely the same question in mind, so you saved me the effort of writing it. Now I'm going to read the answers, hopefully they will clarify the matter.


#5

Gabe - very much appreciate your detailed explanation. I've read it a couple times and I think I'm mostly following. I think the one thing I'm not following fully is the super in the subclass. I'll play in repl.it and get back to you.

Thanks!


#6

Glad to help, Sam! :slightly_smiling:


#7

Thanks so much for this question @pyrunner43701 and response @g4be.


#8

this is a really nice and well done Q&A :smiley: