One of the basic precepts of object oriented programming is that subtyping represents the "is-a" relationship. That is, the child is always a specific form of the parent. A common example is that a square is a specific form of rectangle, so it seems to make sense to make a Square class inherit from a Rectangle class. (read here why that doesn't actually make sense - thanks @KevinKrumwiede for pointing this out)
Occasionally, one encounters a situation where subtyping is a convenient way to write a different relationship.
The one I currently face is relatively simple. I'm controlling a simple mechanical system B, which contains subsystem A. Thus, in meatspace, we see a very literal "has-a" relationship: System B has a System A.
Writing the code as a close analogy to reality, I wound up with something like the following: (Shown in Python for brevity. Actual code is in C++.)
class A:
def m1(self): print "A.m1"
def m2(self): print "A.m2"
def m3(self, arg): print "A.m3(" + arg + ")"
class B:
def __init__(self): self.a = A()
def m1(self): a.m1()
def m2(self): a.m2()
def m3(self): print "B.m3"
def m4(self): a.m3("B.m4")
While class B contributes useful functionality (in the real life version), a bunch of its methods are simple pass-throughs. Class B just doesn't have anything useful to add to m1() or m2() - it just needs to expose them to the owners of B objects.
If we throw out the precept that inheritance should represent an "is-a" relationship, we could simplify things:
class A:
def m1(self): print "A.m1"
def m2(self): print "A.m2"
def m3(self, arg): print "A.m3(" + arg + ")"
class B(A):
def __init__(self): pass
def m3(self): print "B.m3"
def m4(self): a.m3("B.m4")
Now all methods of A are exposed as if they belong to B. B can (and does) override methods of A as needed. The maintainer of B doesn't need to update B every time that A adds a new method - passthroughs are free.
This feels wrong somehow, but I can't fully figure out why. Is this an abuse of the technicalities of the inheritance mechanism? Is it ever appropriate to represent a "has-a" relationship this way? B is not a more specific form of A, but we've subclassed it as if it was.
The only practical drawback I can think of is that all of A's methods are now available for calling, and B has little to no way to prevent this. In a language like Python, there's no concept of private methods, so that doesn't matter. In a language like C++ it might. Do other drawbacks exist?
Edit: To all who find this question in the future, be sure to read this answer as well as the accepted answer. Both list noteworthy drawbacks to using inheritance to accomplish composition.