为什么我们不需要动态语言中的接口?

时间:2010-06-17 14:44:15

标签: c# java python dynamic-languages

仅仅是因为动态类型我们在python中不需要接口的概念(比如在Java和C#中)吗?

9 个答案:

答案 0 :(得分:23)

作为关键字和工件的interface是由Java 1 引入的(C#从那里开始)来描述对象必须遵守的合同。

但是,接口一直是面向对象范式的关键部分,基本上它代表了一个对象必须响应的方法。 Java只是强制执行此机制来提供静态类型检查。

因此,动态(OO)编程语言使用接口,甚至认为它们不会静态检查它们。就像其他数据类型一样,例如在Ruby中:

 @i = 1;

您不必声明只使用i类型的FixNum。接口也是如此,它们只是流动。权衡是,您不能对此进行静态检查,故障仅在运行时显示。

另一方面{* 3}}(或称为静态鸭子类型,我称之为P)被语言用作Go或Scala,它提供了两全其美的效果。

<子> 1.请参阅Daniel Earwicker关于CORBA interface关键字

的评论

答案 1 :(得分:5)

我们不要求他们,但我们支持他们。查看Zope Interfaces(可以在Zope之外使用)。

答案 2 :(得分:1)

接口构造用于静态类型语言,以教授类型系统哪些对象在特定的方法调用上下文中可互相替换。如果两个对象实现相同的方法但通过从公共基类或公共接口的实现继承而不相关,则类型系统将在编译时引发错误,如果您将一个替换为另一个。

动态语言使用“duck typing”,这意味着只需在运行时查找该方法,如果它存在正确的签名,则使用它;否则会产生运行时错误。如果两个对象都通过实现相同的方法“像鸭子一样嘎嘎叫”,那么它们是可替代的。因此,没有明确需要语言通过基类或接口将它们联系起来。

话虽如此,作为概念的接口在动态世界中仍然非常重要,但它们通常只是在文档中定义而不是由语言强制执行。偶尔,我看到程序员实际上创建了一个基类,为此目的勾勒出界面;这有助于形式化文档,如果界面的一部分可以根据界面的其余部分实现,则特别有用。

答案 3 :(得分:1)

值得注意的是,与许多人会说的第一个响应相反,接口可以用来做更多的事情来记录“一个类支持什么方法”。 Grzenio用他的措辞“实现相同的行为”来触及这一点。作为此的具体示例,请查看Java接口Serializable。它没有实现任何方法;相反,它被用作“标记”来表示该类可以安全地序列化。

当考虑这种方式时,使用接口的动态语言可能是合理的。话虽这么说,类似于注释的东西可能是一种更合理的方法。

答案 4 :(得分:1)

关于至少一些动态语言使得显式接口有点尴尬的一个关键因素是,动态语言通常可以响应事先不知道的消息(错误,“方法调用”),甚至做事情喜欢在飞行中创建方法。了解对象是否正确响应消息的唯一真正方法是向其发送消息。没关系,因为动态语言认为能够支持那种事情而不是静态类型检查会更好;一个对象被认为可以在特定协议中使用,因为它“已知”能够参与该协议(例如,由于被另一个消息给出)。

答案 5 :(得分:1)

Perl有角色(或特征),它不仅仅是java perl角色的接口,我们可以通过实现查看这些链接,了解有关perl角色的更多信息

答案 6 :(得分:0)

接口用于静态类型语言,以描述两个独立的对象“实现相同的行为”。在动态类型语言中,隐含地假设当两个对象具有相同名称/ params的方法时,它会做同样的事情,因此接口是没有用的。

答案 7 :(得分:0)

在C#和Java中,接口只是带有所有抽象方法的抽象类。它们的存在是为了允许伪多重继承而不实际支持完全多重继承和多重继承产生的歧义。

Python支持multiple inheritance,并且当多个父项中存在方法时,它有自己的方法来确定应该调用哪个父方法。

答案 8 :(得分:0)

动态语言是Duck Typed

  

如果它像鸭子一样走路而且嘎嘎叫   像鸭子,它一定是鸭子

http://en.wikipedia.org/wiki/Duck_typing

换句话说,如果你想要一个对象来支持Delete()方法,那么你可以使用

obj.Delete()

方法但如果对象不支持Delete(),则会出现运行时错误。静态类型语言不允许这样做并抛出编译时错误。所以你基本上交易类型安全,以加快开发时间和灵活性。

如果没有接口,您可以在静态语言中执行类似的操作:

void Save(MyBaseClass item)
{
    if (item.HasChanges)
        item.Save()
}

但这需要传递给此方法的每个对象都从MyBaseClass继承。由于Java或C#不支持不灵活的muliinheritance,因为如果你的类已经继承了另一个类,它也不能继承MyBaseClass。因此,更好的选择是创建一个ISavable接口并接受它作为输入参数以确保可以保存该项。然后你最好兼得:安全性和灵活性。

public interface ISavable
{
    bool HasChanges {get;set;}
    void Save();
}

void Save(ISavable item)
{
    if (item.HasChanges)
        item.Save()
}

最后一个后门是使用object作为参数,如果你不能指望每个使用你的save方法的项目来实现这个接口。

void Save(object item)
{
    if (item.HasChanges)
        item.Save()
}

但是,再次,您没有编译时检查,如果有人将您的方法与不兼容的类一起使用,则可能会出现运行时错误。