我一直在玩PHP和Python。
我一直在阅读OO编程中的接口,并且看不到使用它的优势。
多个对象可以实现相同的接口,但多重继承也不能提供这个功能吗?
为什么我需要创建一个“没有实现”的接口 - 主要是“契约” - 如果我可以检查一个方法是否存在于Python中的一个对象中,是否继承了多个类?
接口是用其他语言创建的,因为它们不提供多重继承?或者我在这里错过了一些更重要的东西?
答案 0 :(得分:13)
首先,尽量不要在Python和Java之间进行比较和对比。它们是不同的语言,具有不同的语义。比较和对比只会导致像这样令人困惑的问题,你试图比较Python不使用Java需要的东西。
这很像比较7号和绿色。他们都是名词。除此之外,你将难以比较两者。
这是底线。
Python不需要接口。
Java需要它们。
多个对象可以实现相同的接口,但多重继承也不能提供这个功能吗?
这两个概念几乎没有任何关系。
我可以定义大量共享公共接口的类。在Python中,由于“鸭子打字”,我不必仔细确定它们都有一个共同的超类。
接口是不相交的类层次结构的“intent”声明。它提供了一个通用规范(可以由编译器检查),它不是简单类层次结构的一部分。它允许多个类层次结构实现一些共同特征,并且对于这些特征具有多态性。
在Python中,您可以在没有接口的情况下使用多重继承。多重继承可以包括接口类,也可以不包括接口类。
Java甚至没有多重继承。相反,它使用了一种称为“mixins”的完全不同的技术。
为什么我需要创建一个“没有实现”的接口 - 主要是“契约” - 如果我可以检查一个方法是否存在于Python中的一个对象中,是否继承了多个类?
如果您在Python中创建一个接口,它可以是一种正式合同。声称所有子类绝对会执行接口所声称的内容。
当然,numbskull完全可以自由撒谎。他们可以从接口继承并错误地实现一切。没有什么能阻止反社会的不良行为。
您在Java中创建一个接口,以允许多类对象具有共同的行为。由于您没有在Python中告诉编译器,因此该概念甚至不适用。
接口是用其他语言创建的,因为它们不提供多重继承?
由于概念不相关,因此很难回答这个问题。
在Java中,他们使用“mixin”而不是多重继承。 “界面”允许一些混合附加功能。这是界面的一种用途。
接口的另一个用途是将“is”与“does”分开。类层次结构定义了对象的内容。接口层次结构定义了类的功能。
在大多数情况下,IS和DOES是同构的,所以没有区别。
在某些情况下,对象是什么以及对象有什么不同。
答案 1 :(得分:11)
接口的用处与静态类型的有用性直接相关。如果您使用的是动态类型语言(如PHP或Python),那么界面确实不会显着增加语言的表现力。也就是说,任何可以被描述为使用接口的程序都可以在没有使用接口的情况下表达而没有显着差异。
因此,Python有一个相当模糊的“协议”概念(符合特定模式的实现,如iteration protocol),这基本上是相同的,但没有编译的其他好处 - 时间检查其价值是有限的。
另一方面,在静态类型语言中,接口对于允许实现与实现分离是必不可少的。在静态语言中,必须在编译时解析所有表达式的类型,因此通常必须在此时绑定到实现,从而限制了运行时的灵活性。接口定义如何访问功能而不定义特定的实现,这允许静态语言证明表达式是正确的,而无需访问实现。
如果没有接口(或像C ++的纯虚函数那样的等效公式),静态类型语言的表现力将受到严重阻碍。实际上,存在许多实现(Win32和COM立即想到)通过在结构中存储函数指针(因此重新实现C ++的虚函数和手动vtable调用)来实质上重现C中的接口和虚拟调度的大部分功能。 。在这种情况下,表现力存在很大差异,因为程序中需要进行许多更改才能表达相同的概念。
接口只是类型多态的一个例子,而且相当有限。在支持parametric polymorphism(又名泛型)的语言中,您可以完成更多任务。 (例如,没有通用接口,C#的LINQ是不可能的。)对于同类事物的更强大的形式,请查看Haskell的typeclasses。
答案 2 :(得分:5)
即使是像Python这样的鸭子类型的语言,界面也可以更明确地表达你的意图。如果您有许多实现,并且它们共享一组方法,那么接口可以是记录这些方法的外部行为的好方法,为概念赋予名称,并使概念具体化。
如果没有显式接口,系统中有一个没有物理表示的重要概念。这并不意味着您必须使用接口,但接口提供了这种具体性。
答案 3 :(得分:4)
在动态类型语言中,如PHP和Python,接口的用途有限。您可以尝试在任何对象上调用方法,如果它不存在则会出现运行时错误。
它是静态类型语言,如Java和.NET,接口变得很重要,因为在编译时检查方法及其参数。
现在,对于接口:
除了数组之外,Java还有List
个。作为一般规则,数组用于基元(主要是数字类型),而List
用于对象。
我可以有一个List<String>
,这是一个字符串列表。我知道我可以add
字符串,并且get
字符串可以从中恢复。
我不知道它是哪个实现。它可以是ArrayList
(由数组支持的列表),LinkedList
(由双向链表支持的列表),CopyOnWriteArrayList
(ArrayList
的线程安全版本)等等......
感谢多态和接口,我不需要知道对List
执行List
操作的类型{/ 1}}。
答案 4 :(得分:3)
因为你想要program against an interface而不是具体的实现(GoF 1995:18)
答案 5 :(得分:1)
答案 6 :(得分:1)
是即可。至于PHP,接口只是克服缺少多重继承的一种手段。对IDE有一些小的语义差异,接口引起的冲突更少,这显然有助于新手程序员。但如前所述,在动态语言中并不是绝对必要的。 http://c2.com/cgi/wiki?MultipleInheritance
答案 7 :(得分:1)
请阅读有关python中Zope接口功能的Twisted Framework文章。
答案 8 :(得分:0)
通常实现替换多重继承(C#)。 我认为一些语言/程序员也会使用它们来强制执行对象结构的要求。