Java abstract/interface design in Python Java abstract/interface design in Python python python

Java abstract/interface design in Python


There's a bit of a story behind interfaces in Python. The original attitude, which held sway for many years, is that you don't need them: Python works on the EAFP (easier to ask forgiveness than permission) principle. That is, instead of specifying that you accept an, I don't know, ICloseable object, you simply try to close the object when you need to, and if it raises an exception then it raises an exception.

So in this mentality you would just write your classes separately, and use them as you will. If one of them doesn't conform to the requirements, your program will raise an exception; conversely, if you write another class with the right methods then it will just work, without your needing to specify that it implements your particular interface.

This works pretty well, but there are definite use cases for interfaces, especially with larger software projects. The final decision in Python was to provide the abc module, which allows you to write abstract base classes i.e. classes that you can't instantiate unless you override all their methods. It's your decision as to whether you think using them is worth it.

The PEP introducing ABCs explain much better than I can:

In the domain of object-oriented programming, the usage patterns forinteracting with an object can be divided into two basic categories,which are 'invocation' and 'inspection'.

Invocation means interacting with an object by invoking its methods.Usually this is combined with polymorphism, so that invoking a givenmethod may run different code depending on the type of an object.

Inspection means the ability for external code (outside of theobject's methods) to examine the type or properties of that object,and make decisions on how to treat that object based on thatinformation.

Both usage patterns serve the same general end, which is to be able tosupport the processing of diverse and potentially novel objects in auniform way, but at the same time allowing processing decisions to becustomized for each different type of object.

In classical OOP theory, invocation is the preferred usage pattern,and inspection is actively discouraged, being considered a relic of anearlier, procedural programming style. However, in practice this viewis simply too dogmatic and inflexible, and leads to a kind of designrigidity that is very much at odds with the dynamic nature of alanguage like Python.

In particular, there is often a need to process objects in a way thatwasn't anticipated by the creator of the object class. It is notalways the best solution to build in to every object methods thatsatisfy the needs of every possible user of that object. Moreover,there are many powerful dispatch philosophies that are in directcontrast to the classic OOP requirement of behavior being strictlyencapsulated within an object, examples being rule or pattern-matchdriven logic.

On the other hand, one of the criticisms of inspection by classic OOPtheorists is the lack of formalisms and the ad hoc nature of what isbeing inspected. In a language such as Python, in which almost anyaspect of an object can be reflected and directly accessed by externalcode, there are many different ways to test whether an object conformsto a particular protocol or not. For example, if asking 'is thisobject a mutable sequence container?', one can look for a base classof 'list', or one can look for a method named '_getitem_'. But notethat although these tests may seem obvious, neither of them arecorrect, as one generates false negatives, and the other falsepositives.

The generally agreed-upon remedy is to standardize the tests, andgroup them into a formal arrangement. This is most easily done byassociating with each class a set of standard testable properties,either via the inheritance mechanism or some other means. Each testcarries with it a set of promises: it contains a promise about thegeneral behavior of the class, and a promise as to what other classmethods will be available.

This PEP proposes a particular strategy for organizing these testsknown as Abstract Base Classes, or ABC. ABCs are simply Python classesthat are added into an object's inheritance tree to signal certainfeatures of that object to an external inspector. Tests are done usingisinstance(), and the presence of a particular ABC means that the testhas passed.

In addition, the ABCs define a minimal set of methods that establishthe characteristic behavior of the type. Code that discriminatesobjects based on their ABC type can trust that those methods willalways be present. Each of these methods are accompanied by angeneralized abstract semantic definition that is described in thedocumentation for the ABC. These standard semantic definitions are notenforced, but are strongly recommended.

Like all other things in Python, these promises are in the nature of agentlemen's agreement, which in this case means that while thelanguage does enforce some of the promises made in the ABC, it is upto the implementer of the concrete class to insure that the remainingones are kept.


I'm not that familiar with Python, but I would hazard a guess that it doesn't.

The reason why interfaces exist in Java is that they specify a contract. Something that implements java.util.List, for example, is guaranteed to have an add() method to conforms to the general behaviour as defined on the interface. You could drop in any (sane) implementation of List without knowing its specific class, call a sequence of methods defined on the interface and get the same general behaviour.

Moreover, both the developer and compiler can know that such a method exists and is callable on the object in question, even if they don't know its exact class. It's a form of polymorphism that's needed with static typing to allow different implementation classes yet still know that they're all legal.

This doesn't really make sense in Python, because it's not statically typed. You don't need to declare the class of an object, nor convince the compiler that methods you're calling on it definitely exist. "Interfaces" in a duck-typing world are as simple as invoking the method and trusting that the object can handle that message appropriately.

Note - edits from more knowledgeable Pythonistas are welcome.


May be you can use something like this. This will act as an abstract class. Every subclass is thus forced to implement func1()

class Abstract:    def func1(self):        raise NotImplementedError("The method not implemented")