What’s the point of inheritance in Python?

前端 未结 11 2082
一向
一向 2020-12-12 10:11

Suppose you have the following situation

#include 

class Animal {
public:
    virtual void speak() = 0;
};

class Dog : public Animal {
             


        
相关标签:
11条回答
  • 2020-12-12 11:10

    Inheritance in Python is more of a convenience than anything else. I find that it's best used to provide a class with "default behavior."

    Indeed, there is a significant community of Python devs who argue against using inheritance at all. Whatever you do, don't just don't overdo it. Having an overly complicated class hierarchy is a sure way to get labeled a "Java programmer", and you just can't have that. :-)

    0 讨论(0)
  • 2020-12-12 11:11

    It's not inheritance that duck-typing makes pointless, it's interfaces — like the one you chose in creating an all abstract animal class.

    If you had used an animal class that introduce some real behavior for its descendants to make use of, then dog and cat classes that introduced some additional behavior there would be a reason for both classes. It's only in the case of the ancestor class contributing no actual code to the descendant classes that your argument is correct.

    Because Python can directly know the capabilities of any object, and because those capabilities are mutable beyond the class definition, the idea of using a pure abstract interface to "tell" the program what methods can be called is somewhat pointless. But that's not the sole, or even the main, point of inheritance.

    0 讨论(0)
  • 2020-12-12 11:14

    Another small point is that op's 3'rd example, you can't call isinstance(). For example passing your 3'rd example to another object that takes and "Animal" type an calls speak on it. If you do it don't you would have to check for dog type, cat type, and so on. Not sure if instance checking is really "Pythonic", because of late binding. But then you would have to implement some way that the AnimalControl doesn't try to throw Cheeseburger types in the truck, becuase Cheeseburgers don't speak.

    class AnimalControl(object):
        def __init__(self):
            self._animalsInTruck=[]
    
        def catachAnimal(self,animal):
            if isinstance(animal,Animal):
                animal.speak()  #It's upset so it speak's/maybe it should be makesNoise
                if not self._animalsInTruck.count <=10:
                    self._animalsInTruck.append(animal) #It's then put in the truck.
                else:
                    #make note of location, catch you later...
            else:
                return animal #It's not an Animal() type / maybe return False/0/"message"
    
    0 讨论(0)
  • 2020-12-12 11:15

    You are referring to the run-time duck-typing as "overriding" inheritance, however I believe inheritance has its own merits as a design and implementation approach, being an integral part of object oriented design. In my humble opinion, the question of whether you can achieve something otherwise is not very relevant, because actually you could code Python without classes, functions and more, but the question is how well-designed, robust and readable your code will be.

    I can give two examples for where inheritance is the right approach in my opinion, I'm sure there are more.

    First, if you code wisely, your makeSpeak function may want to validate that its input is indeed an Animal, and not only that "it can speak", in which case the most elegant method would be to use inheritance. Again, you can do it in other ways, but that's the beauty of object oriented design with inheritance - your code will "really" check whether the input is an "animal".

    Second, and clearly more straightforward, is Encapsulation - another integral part of object oriented design. This becomes relevant when the ancestor has data members and/or non-abstract methods. Take the following silly example, in which the ancestor has a function (speak_twice) that invokes a then-abstract function:

    class Animal(object):
        def speak(self):
            raise NotImplementedError()
    
        def speak_twice(self):
            self.speak()
            self.speak()
    
    class Dog(Animal):
        def speak(self):
            print "woff!"
    
    class Cat(Animal):
        def speak(self):
            print "meow"
    

    Assuming "speak_twice" is an important feature, you don't want to code it in both Dog and Cat, and I'm sure you can extrapolate this example. Sure, you could implement a Python stand-alone function that will accept some duck-typed object, check whether it has a speak function and invoke it twice, but that's both non-elegant and misses point number 1 (validate it's an Animal). Even worse, and to strengthen the Encapsulation example, what if a member function in the descendant class wanted to use "speak_twice"?

    It gets even clearer if the ancestor class has a data member, for example "number_of_legs" that is used by non-abstract methods in the ancestor like "print_number_of_legs", but is initiated in the descendant class' constructor (e.g. Dog would initialize it with 4 whereas Snake would initialize it with 0).

    Again, I'm sure there are endless more examples, but basically every (large enough) software that is based on solid object oriented design will require inheritance.

    0 讨论(0)
  • 2020-12-12 11:15

    Inheritance in Python is all about code reuse. Factorize common functionality into a base class, and implement different functionality in the derived classes.

    0 讨论(0)
提交回复
热议问题