
"GvR" == Guido van Rossum <guido@python.org> writes:
This discussion appears about over, but I haven't seen any solutions via inheritance. Other languages that lack true interfaces use abstract base classes. Python supports multiple inheritance. Isn't this enough?
GvR> I haven't given up the hope that inheritance and interfaces GvR> could use the same mechanisms. But Jim Fulton, based on years GvR> of experience in Zope, claims they really should be different. GvR> I wish I understood why he thinks so. Here's a go at explaining why the mechanisms need to be separate. I'm loathe to channel Jim, but I think he'd agree. We'd like to use interfaces to make fairly strong claims. If a class A implements an interface I, then we should be able to use an instance of A anywhere that an I is needed. This is just the straightforward notion of substitutability. I'm saying this is a strong claim because we want an A to behave like an I. By behave, I mean that the interface I can describe behavior beyond just a method name or signature. Why can't we use the current inheritance mechanism to implement the interface concept? Because the inheritance mechanism is too general. If we take the class A, anyone can create a subclass of it, regardless of whether that subclass implements I. Say you wanted to write LBYL code that tests whether an object implements an interface. If you use a marker class and isinstance() for the test, the inheritance rules makes it impossible to express some relationships. In particular, it is impossible to write a class B that inherits from A, but does not implement I. Since our test is isinstance(), any subclass of A will appear to implement I. This is unfortunate, because inheritance is a great implementation trick that shouldn't have anything to do with the interface. If we think about it briefly in terms of types. (Python doesn't have the explicit types, but sometimes we reason about programs as if they did.) Strongly typed OO languages have to deal in some way with subclasses that are not subtypes. Some type systems require covariance or contravariance or invariance. In some cases, you can write a class that is a subclass but is not a subtype. The latter is what we're hoping to achieve with interfaces. If we imagined an interface statement that was explicit and no inherited, then we'd be okay. class A(SomeBase): implements I class B(A): implements J Now we've got a class A that implements I and a subclass B that implements J. The test isinstance(B(), A) is true, but the test implements(B(), I) is not. It's quite helpful to have the implements() predicate which uses a rule different from isinstance(). If we don't have the separate interface concept, the language just isn't as expressive. We would have to establish a convention to sacrifice one of -- a) being able to inherit from a class just for implementation purposes or b) being able to reason about interfaces using isinstance(). a) is error prone, because the language wouldn't prevent anyone from making the mistake. b) is unfortunate, because we'd have interfaces but no formal way to reason about them. Jeremy