Program to an interface, not an implementation

Gordon Scott gscott at peregrine.com
Fri Jun 7 11:43:23 EDT 2002


"My next problem is on nearly the same page (17) of the GoF book:
 class versus interface (== type) inheritance, but in the python context.

 In C++ and Eiffel inheritance means both interface and implementation
 inheritance and in Smalltalk inheritance means just implementation
inheritance.
 I don't know any of these languages."

   To understand this comment that they make you have to make sure you've
got the 
previous distinction they make between an objects class and an objects type.
An objects CLASS is an objects IMPLEMENTATION, while an objects TYPE is the 
INTERFACE or functions it has.  Note that an object has ONE implementation
but can
have MANY types.
   Unfortunately the best example I have is the C++/Java vs Smalltalk/Python
example.
Perhaps if you said what languages you were familiar with we might be able
to provide
more relevant examples.  But I hope you'll get enough to make sense of
this...

   In C++ (and perhaps to some extent) Java, a class is simply a template
for instantiating
objects.  Because of the static typing of C++/Java an objects class and type
are directly
tied together.  The class directly defines an objects type  You can't have
one w/o the other.
Meaning you can't try and call an operation on an object unless it was
explicitly defined when
the code was compiled.
  Example, if you want to have a piece of client code that performs the same
operation on two
different objects, those two different objects must both be subclasses of a
common parent.
This is class inheritance. C++ is going to force you to cast these objects
to a specific type
(the parent) before you can call the common method.  So now you have two
different objects of
the same type, but they are forced to share implementation since you had to
use class inheritance
to do it.  I'll avoid the technicalities of pure virtual/abstract classes
here, the point is the
same.
   Example again of the common widgets..in c++ the classes would be forced
to inherit from a 
common parent.  Class Widget would define Draw() operation.  Class Button
and Class Text would
be subclasses of Widget and would override Draw().  If you want to place
both of these objects into
a collection you'd have to specifically cast them to a Wdiget.

   With Smalltalk and Python things are much different.  Not only do you
have dynamic typing, but
classes are themselves objects that you can manipulate and call operations
on.  The dynamic typing
brings us back to the answers from your previous question.  Due to the
dynamic typing, two objects
only have to have the same operations defined to share types, REGARDLESS of
their implementations or
class relationships.  You can TRY and call any operation on ANY object, if
its there great all is well,
if not you'll get a runtime exception.
   Example again in Python of file-like object.  Assume your client code has
a collection of objects 
that it performs reads and writes to.  In python those objects can be
sockets, files, or stringIO's since
those object share the same type, ie all have read and write methods.
However none of those objects share any sort of implementation, meaning they
are not subclasses of a common ancestor.

  So class inheritance is standard classing and subclassing, whereas
interface inheritance is multiple
objects having the same type.  With interface inheritance you can swap in
and out different objects into
your client code regardless of the implementation/class that they are, and
all will work well.

For C++ interface inheritance REQUIRES class inheritance.  For
Python/Smalltalk, it does not.

-----Original Message-----
From: Eric Brunel [mailto:eric.brunel at pragmadev.com]
Sent: Friday, June 07, 2002 9:31 AM
To: python-list at python.org
Subject: Re: Program to an interface, not an implementation


Egbert Bouwman wrote:
> All your comments are crystal clear. Thanks.
> 
> My next problem is on nearly the same page (17) of the GoF book:
> class versus interface (== type) inheritance, but in the python context.
> 
> "In C++ and Eiffel inheritance means both interface and implementation
> inheritance" and
> "in Smalltalk inheritance means just implementation inheritance".
> I don't know any of these languages.
> 
> Now in my simplistic worldview, if you inherit from a class,
> you inherit everything, implementation and interface,
> because the implementation defines the interface as well.
> Even if all methods of the superclass only contain 'pass'.
> But I may be wrong.

I know C++ and I looked at SmallTalk a bit, and it seems the line between 
"implementation + interface" and "implementation only" inheritance is very 
thin... Apparently, it's quite directly related to strong typing and 
declarations. "Interface", in this context, seems to describe what's 
declared. So, as you noted in the beginning of your post, an "interface" is 
considered as a declared type. Since SmallTalk claims to have no types at 
all (which is also the case with Python...), they claim not to have such 
thing as an "interface", so obviously they cannot inherit it...

In fact, I don't see the point in this: as you noted, when a class inherits 
from another, it inherits everything, implementation and interface. So in 
practice, it's not really significant. As I understand it, the only 
practical consequence of this distinction *may* be in the following case:

class A:
  def m(self, i):
    pass
class B(A):
  def m(self, i, j):
    pass

In Python or SmallTalk, the preceding code is completely valid, so one 
could say that the "interface" of class A was not inherited by class B, 
since its method m has a different signature than A's method m.

Trying to do the same thing in interface-inheriting languages would not 
have the same effect at all: it would either be forbidden, or even have 
stranger consequences. In C++ or Java, it would declare a *second* method, 
also called m, that would be distinguished from the inherited one by its 
number of parameters or their type:

public class A {
  public int m(int i) {
    ...
  }
}
public class B inherits A {
  public int m(int i, int j) {
    ...
  }
}
...
o = new B();
o.m(1)      // Calls A.m
o.m(1, 2)   // Calls B.m

So, as you see, you probably can live without knowing anything about all 
this and still be able to do great stuff with whatever language you like 
:-).

However, if anybody knows a bit more than me about implementation/interface 
inheritance, I'd be glad to learn (I happen to teach OO sometimes and I'd 
like to be able to answer this question precisely if it ever gets answered 
to me ;-).
-- 
- Eric Brunel <eric.brunel at pragmadev.com> -
PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com
-- 
http://mail.python.org/mailman/listinfo/python-list





More information about the Python-list mailing list