I have an idea for an interface mechnism for Python, and I'd like to see if anyone likes it before writing an actual PEP. The key features are: - It's implementable in pure Python (I've already started working on it). - The syntax to use it is fairly concise. - Interfaces are inherited by default, but can be turned off. - Classes are made to implement interfaces without altering the class definition in any way. - A class can support any number of interfaces, even multiple interfaces that define methods with the same names. - It's easily extensible to add new features in a backward-compatible way. - It has support for design-by-contract idioms (this part is not essential to the proposal, so I won't discuss it further here, but interfaces without DBC seem kind of incomplete to me). Basic Usage =========== In actual practice it would look something like this: Suppose you have a class like this: class SomeClass: def foo(...): ... def bar(...): ... def foo2(...): ... In the simplest case, suppose you have an interface Foo that defines a single method, foo. To declare that SomeClass implements foo, you'd say: Foo.bind(SomeClass) Now, suppose you have a function that requires an argument implemeting interface Foo. You would probably code it like this: def foo_proc(foo_arg): foo_proxy = Foo(foo_arg) ... x = foo_proxy.foo(...) ... Two things are happening here. First, foo_arg is being checked to make sure it implements Foo; if not, an InterfaceError will be raised. Then, foo_proxy becomes a proxy for foo_arg, but it *only* supports calling the method foo, since that's all the interface defines. (If foo_arg is already a proxy object, the call the Foo will just return foo_arg.) Defining an Interface ===================== How is "Foo" defined? It could look something like this: class Foo(interface): def doc_foo(self,...): "Docstring for foo method." The "doc_" prefix on foo is not part of the method name; it is needed to control how the interface treats the method. If the method has default behavior, you could say this instead: class Foo(interface): def default_foo(self,...): "Docstring for foo method." print "Defaults can be handy." In the version, unlike the first, classes implemeting Foo need not define their own "foo" method is the defualt will suffice. Requiring some sort of prefix attached to every name defined by the interface is a little ugly, but it opens up a lot of possibilities for creating different behaviors with a minimum of fuss--I have a lot of uses in mind for different prefixes that I won't go into here. Advanced Examples ================= Let's say we have a new interface, FooBar, defined like this: class FooBar(interface): def doc_foo(...): "Method foo." def doc_bar(...): "Method quux." And suppose we'd like to make SomeClass above implement FooBar, but we want FooBar.foo to call SomeClass.foo2 instead of SomeClass.foo. It's easy! FooBar.bind(SomeClass) FooBar[SomeClass].foo = "foo2" # Override default binding. Now we can do really confusing stuff: x = SomeClass() Foo(x).foo() # Calls x.foo() FooBar(x).foo() # Calls x.foo2() Of course you probably wouldn't do something so confusing on purpose, but it could be useful when an object must support two different interfaces (written by different people) that happen to have method names in common, or to connect a class to an interface where the class defines all the needed functionality but the methods have the wrong names. For the last trick, let's imagine you want to derive a subclass of SomeClass. If you want the new class to inherit all the interfaces, do nothing. To remove an inteface, just do something like this: class AnotherClass(SomeClass): ... Foo.unbind(AnotherClass) And it's done! Please let me know if you like this idea (or hate it). If I get a good response I'll try to write a PEP this weekend and make the implementation availble to try out. --jw
John, I like your idea! I would look forward to seeing the implementation. I personally prefer to have the "interface binding" to be part of a class definition. However, I can see some advantages to having the binding process seperate from the interface. Good day, ~Mark On September 27, 2002 02:51 pm, John Williams wrote:
participants (2)
-
John Williams
-
Mark Nenadov