Suppose you have the following situation
#include
class Animal {
public:
virtual void speak() = 0;
};
class Dog : public Animal {
In C++/Java/etc, polymorphism is caused by inheritance. Abandon that misbegotten belief, and dynamic languages open up to you.
Essentially, in Python there is no interface so much as "the understanding that certain methods are callable". Pretty hand-wavy and academic-sounding, no? It means that because you call "speak" you clearly expect that the object should have a "speak" method. Simple, huh? This is very Liskov-ian in that the users of a class define its interface, a good design concept that leads you into healthier TDD.
So what is left is, as another poster politely managed to avoid saying, a code sharing trick. You could write the same behavior into each "child" class, but that would be redundant. Easier to inherit or mix-in functionality that is invariant across the inheritance hierarchy. Smaller, DRY-er code is better in general.
You can get around inheritance in Python and pretty much any other language. It's all about code reuse and code simplification though.
Just a semantic trick, but after building your classes and base classes, you don't even have to know what's possible with your object to see if you can do it.
Say you have d which is a Dog that subclassed Animal.
command = raw_input("What do you want the dog to do?")
if command in dir(d): getattr(d,command)()
If whatever the user typed in is available, the code will run the proper method.
Using this you can create whatever combination of Mammal/Reptile/Bird hybrid monstrosity you want, and now you can make it say 'Bark!' while flying and sticking out its forked tongue and it will handle it properly! Have fun with it!
I don't see much point in inheritance.
Every time I have ever used inheritance in real systems, I got burned because it led to a tangled web of dependencies, or I simply realised in time that I would be a lot better off without it. Now, I avoid it as much as possible. I simply never have a use for it.
class Repeat:
"Send a message more than once"
def __init__(repeat, times, do):
repeat.times = times
repeat.do = do
def __call__(repeat):
for i in xrange(repeat.times):
repeat.do()
class Speak:
def __init__(speak, animal):
"""
Check that the animal can speak.
If not we can do something about it (e.g. ignore it).
"""
speak.__call__ = animal.speak
def twice(speak):
Repeat(2, speak)()
class Dog:
def speak(dog):
print "Woof"
class Cat:
def speak(cat):
print "Meow"
>>> felix = Cat()
>>> Speak(felix)()
Meow
>>> fido = Dog()
>>> speak = Speak(fido)
>>> speak()
Woof
>>> speak.twice()
Woof
>>> speak_twice = Repeat(2, Speak(felix))
>>> speak_twice()
Meow
Meow
James Gosling was once asked at a press conference a question along the lines: "If you could go back and do Java differently, what would you leave out?". His response was "Classes", to which there was laughter. However, he was serious and explained that really, it was not classes that were the problem but inheritance.
I kind of view it like a drug dependency - it gives you a quick fix that feels good, but in the end, it messes you up. By that I mean that it is a convenient way to reuse code, but it forces an unhealthy coupling between child and parent class. Changes to the parent may break the child. The child is dependant on the parent for certain functionality and cannot alter that functionality. Therefore the functionality provided by the child is also tied to the parent - you can only have both.
Better is to provide one single client facing class for an interface which implements the interface, using the functionality of other objects which are composed at construction time. Doing this via properly designed interfaces, all coupling can be eliminated and we provide a highly composable API (This is nothing new - most programmers already do this, just not enough). Note that the implementing class must not simply expose functionality, otherwise the client should just use the composed classes directly - it must do something new by combining that functionality.
There is the argument from the inheritance camp that pure delegation implementations suffer because they require lots of 'glue' methods which simply pass along values through a delegation 'chain'. However, this is simply reinventing an inheritance-like design using delegation. Programmers with too many years of exposure to inheritance-based designs are particularly vulnerable to falling into this trap, as, without realising it, they will think of how they would implement something using inheritance and then convert that to delegation.
Proper separation of concerns like the above code doesn't require glue methods, as each step is actually adding value, so they are not really 'glue' methods at all (if they don't add value, the design is flawed).
It boils down to this:
For reusable code, each class should do only one thing (and do it well).
Inheritance creates classes that do more than one thing, because they are mixed up with parent classes.
Therefore, using inheritance makes classes that are hard to reuse.
I think that it is very difficult to give a meaningful, concrete answer with such abstract examples...
To simplify, there are two types of inheritance: interface and implementation. If you need to inherit the implementation, then python is not so different than statically typed OO languages like C++.
Inheritance of interface is where there is a big difference, with fundamental consequences for the design of your software in my experience. Languages like Python does not force you to use inheritance in that case, and avoiding inheritance is a good point in most cases, because it is very hard to fix a wrong design choice there later. That's a well known point raised in any good OOP book.
There are cases where using inheritance for interfaces is advisable in Python, for example for plug-ins, etc... For those cases, Python 2.5 and below lacks a "built-in" elegant approach, and several big frameworks designed their own solutions (zope, trac, twister). Python 2.6 and above has ABC classes to solve this.
Classes in Python are basically just ways of grouping a bunch of functions and data.. They are different to classes in C++ and such..
I've mostly seen inheritance used for overriding methods of the super-class. For example, perhaps a more Python'ish use of inheritance would be..
from world.animals import Dog
class Cat(Dog):
def speak(self):
print "meow"
Of course cats aren't a type of dog, but I have this (third party) Dog
class which works perfectly, except the speak
method which I want to override - this saves re-implementing the entire class, just so it meows. Again, while Cat
isn't a type of Dog
, but a cat does inherit a lot of attributes..
A much better (practical) example of overriding a method or attribute is how you change the user-agent for urllib. You basically subclass urllib.FancyURLopener
and change the version attribute (from the documentation):
import urllib
class AppURLopener(urllib.FancyURLopener):
version = "App/1.7"
urllib._urlopener = AppURLopener()
Another manner exceptions are used is for Exceptions, when inheritance is used in a more "proper" way:
class AnimalError(Exception):
pass
class AnimalBrokenLegError(AnimalError):
pass
class AnimalSickError(AnimalError):
pass
..you can then catch AnimalError
to catch all exceptions which inherit from it, or a specific one like AnimalBrokenLegError
I think the point of inheritance in Python is not to make the code compile, it is for the real reason of inheritance which is extending the class into another child class, and to override the logic in the base class. However the duck typing in Python makes the "interface" concept useless, because you can just check if the method exist before invokation with no need to use an interface to limit the class structure.