在Python中实现接口?
根据我的了解,Python并没有一个明确的内置功能来实现接口。想象一下这样的情况:
我有一个项目,里面有多个类。其中一些类使用一个特定的方法。这个方法在功能上或逻辑上和这些类没有任何关系,技术上来说,它不应该出现在这些类里,更不用说把这个方法复制粘贴到所有这些类中是多么糟糕的做法。现在,我可以创建一个类,让这些类都继承这个类,这样它们就可以使用这个方法……但问题是,这些类之间没有任何共同点,让它们有一个共同的父类显得很傻。我也可以创建一个单独的类,里面有这个方法,然后把这个类的实例作为参数到处传递,再作为成员函数调用这个方法,但这样看起来也不太好,我真的希望能找到一种更优雅的方式来处理这个问题。
我觉得把所有代码都贴在这里来强调问题并没有什么用,我会用一个简化的模型来专注于我想要表达的内容:
class 1():
def class1_specific_method (self):
common_method()
def common_method()
#some code
return
class 2():
def class2_specific_method (self):
common_method()
def common_method()
#some code
return
common_method的工作方式完全一样,在这两种情况下都是必要的,但与这些类都没有关联。通常,如果是Java,我会使用某个静态类,或者只是为这些类实现一个接口。有没有什么想法可以让这个看起来更干净、更合理呢?
3 个回答
除了接口,另一种选择是使用ABC模块中的抽象类。通过使用抽象类,你可以做到以下几点:
from abc import ABCMeta
class AbstractClass(object):
__metaclass__ = abc.ABCMeta
def CommonMethod(self):
print "Common Method for all subclasses!"
...
class MyClass(AbstractClass):
pass
>>> obj = MyClass()
>>> obj.CommonMethod()
Common Method for all subclasses!
现在你有了一个抽象类,其他类可以从这个抽象类继承一些共同的行为。如果你想要多个接口,可以通过多重继承来实现。
不过,在Python中,多重继承理论上应该让接口变得不必要。在某些情况下,ABCMeta可以提供类似于接口的机制,但这感觉有点像是在强行使用语言的特性。
总结:Python中没有接口,但ABC可以提供一种变通的方法。
补充:还有zope.interface这个东西,但我对它的用法不太熟悉。
为什么不直接把它做成一个顶层函数呢?如果你选择忽略Python相比Java所带来的所有优点(比如模块、顶层/一等函数、鸭子类型),那么没有接口的确会让人觉得不方便。
class 1():
def class1_specific_method (self):
common_method(self)
class 2():
def class2_specific_method (self):
common_method(self)
def common_method(obj)
#some code
return
我觉得使用继承没有什么问题,毕竟Python和Java不一样。Python支持多重继承,这对那些功能类似于Java接口的混合类(mixins)非常有用。比如说,如果你从一个类Class0
继承,你可以这样解决你的问题:
class Class0(object):
...
class Class1(Class0, CommonMethodsMixin):
def class1_specific_method (self):
common_method()
class Class2(Class0, CommonMethodsMixin):
def class2_specific_method (self):
common_method()
class CommonMethodsMixin(object):
def common_method():
...
既然你没有任何Class0
,我觉得直接从CommonMethodsMixin
类继承也没什么问题。