代码之家  ›  专栏  ›  技术社区  ›  Rene Saarsoo

动态语言中的接口有什么意义吗?

  •  24
  • Rene Saarsoo  · 技术社区  · 16 年前

    否则类型系统不会让你做某些事情。 但是在PHP和Python这样的动态语言中 鸭子打字 .

    PHP支持接口。 所以没有他们,你显然可以幸福地生活。

    我大部分时间都在用PHP做我的工作,从来没有 利用定义接口的能力。当我需要一个 我只是在文档中描述。

    那么,你觉得呢?不使用不是更好吗

    17 回复  |  直到 15 年前
        1
  •  17
  •   davidavr    16 年前

    我认为这更像是一种便利。如果有一个函数接受一个“类文件”对象,并且只对其调用read()方法,那么强迫用户实现某种类型的文件接口是不方便的,甚至是有限制的。检查对象是否有read方法同样简单。

    但是,如果您的函数需要大量方法,则更容易检查对象是否支持接口,然后检查每个方法的支持。

        2
  •  10
  •   Allain Lalonde    16 年前

    是的,有一点

    如果不显式地使用接口,那么代码仍然像实现某些方法一样使用对象,只是不清楚未声明的接口是什么。

    如果您定义了一个函数来接受一个接口(用PHP来说),那么它将在前面失败,问题将出在调用方而不是方法上。一般来说,早退是一个很好的经验法则。

        3
  •  9
  •   Robert Sanders    16 年前

    接口实际上为拥有它们的静态语言(如Java)增加了一定程度的动态语言灵活性。它们提供了一种查询对象的方法,该对象实现了契约 运行时

    这个概念很好地移植到动态语言中。当然,这取决于您对“动态”一词的定义,甚至包括Objective-C,它在Cocoa中非常广泛地使用协议。

    在鲁比我可能会问

    object.respond_to? :sync
    

    所以,是的,它有一个名为“sync”的方法,不管这是什么意思。

    在Objective-C中,我可能会问类似的问题,即“这个看起来/走路/嘎嘎叫像是同步的东西吗?”:

    [myObject respondsToSelector:@selector(sync)]
    

    更好的是,以一些冗长的内容为代价,我可以问一些更具体的问题,例如,“这个看起来/走路/嘎嘎叫像是与MobileMe同步的东西吗?”:

    [myObject respondsToSelector:@selector(sync:withMobileMeAccount:)]
    

    那是鸭子在物种层次上的分类。

    但要问一个对象是否有希望实现与MobileMe的同步。。。

    [receiver conformsToProtocol:@protocol(MobileMeSynchronization)]
    

    当然,您可以通过检查一系列选择器的存在来实现协议,这些选择器是您考虑的协议/duck的定义,并且它们是否足够具体。在哪一点上,这个协议仅仅是一大块丑陋回应的缩写?查询和一些非常有用的语法糖供编译器/IDE使用。

    对于更复杂的库或类层次结构来说,它无疑比大多数应用程序代码更有用,但我认为这个概念在任何语言中都是有用的。

    另外,还有人提到了混音。RubyMixins是一种共享代码的方式——例如,它们与类的实现相关。接口/协议是关于类或对象的接口。它们实际上可以相互补充。您可能有一个指定行为的接口,以及一个或多个帮助对象 实施

    当然,我想不出任何一种语言都有明显的一级语言特征。在那些有mixin的系统中,包括mixin通常意味着它实现的接口。

        4
  •  4
  •   Bite code    16 年前

    如果您没有高度的安全约束(因此没有人会以您不希望的方式访问您的数据),并且您有良好的文档或训练有素的编码人员(因此他们不需要解释器/编译器来告诉他们该做什么),那么不,这是无用的。

        5
  •  3
  •   David Webb    16 年前

    我的印象是 Python doesn't have interfaces . 据我所知,在Python中,不能强制在编译时实现方法,因为它是一种动态语言。

    有一些Python的接口库,但我没有使用其中的任何一个。

    Python也有Mixin,因此可以通过定义Mixin和having来创建接口类 pass 对于每个方法实现,但这并没有给您带来多大价值。

        6
  •  3
  •   marijne    16 年前

        7
  •  2
  •   Community CDub    7 年前

    雷内,求你了 read my answer 在StackOverflow上的“用动态语言构建大型系统的最佳实践”问题。我讨论了放弃动态语言的自由以节省开发工作和轻松地向项目介绍新程序员的一些好处。如果使用得当,接口将大大有助于编写可靠的软件。

        8
  •  2
  •   thr    16 年前

    在像PHP这样的语言中,一个不存在的方法调用会导致一个致命错误并导致整个应用程序崩溃,那么yes接口就有意义了。

    在像Python这样的语言中,您可以捕获和处理无效的方法调用,但它不能。

        9
  •  2
  •   James Hopkin    16 年前

    Abstract Base Classes . 值得一读。

        10
  •  1
  •   S.Lott    16 年前

    Python具有多重继承,因此它不需要接口设计来允许来自多个超类的方法。

    一、 然而,和强类型的一些好处一样——首先,我是早期错误检测的粉丝。我尝试使用“类接口”的抽象超类定义。

    class InterfaceLikeThing( object ):
        def __init__( self, arg ):
            self.attr= None
            self.otherAttr= arg
        def aMethod( self ):
            raise NotImplementedError
        def anotherMethod( self ):
            return NotImplemented
    

    这在某种程度上规范了接口。它并不能为符合期望的子类提供绝对的证据。但是,如果一个子类未能实现所需的方法,我的单元测试将失败 NotImplemented 返回值或 NotImplementedError 例外。

        11
  •  0
  •   gizmo    16 年前

    好吧,首先,Ruby没有像现在这样的接口是对的,但是他们有mixin,wich从其他语言的接口和抽象类中取了一些精华。

    接口的主要目标是确保对象实现接口本身中存在的所有方法。

    当然,接口从来都不是强制性的,即使在Java中,当您不知道要操作哪种对象时,您可以想象只使用类和使用反射来调用方法,但它很容易出错,应该在许多方面加以阻止。

        12
  •  0
  •   Lasse V. Karlsen    16 年前

    好吧,检查一个给定的对象是否支持整个接口肯定会更容易,而不是仅仅 不崩溃

    Duck类型具有一些接口的优点,即在任何地方都易于使用,但检测机制仍然缺失。

        13
  •  0
  •   aib    16 年前

    这就像说在动态类型语言中不需要显式类型。为什么不把所有的东西都变成“var”并在其他地方记录它们的类型呢?

    这是一个由程序员强加给程序员的限制。它使你更难射中自己的脚,给你更少的错误空间。

        14
  •  0
  •   nickf    16 年前

    在我看来,作为一个PHP程序员,接口基本上被用作契约。它允许您说,使用此接口的所有内容都必须实现一组给定的函数。

    我不知道这是否有用,但当我试图理解接口的含义时,我发现它有点绊脚石。

        15
  •  0
  •   wbg    16 年前

    如果您觉得必须这样做,您可以实现一种接口,其中包含一个将对象的方法/属性与给定签名进行比较的函数。下面是一个非常基本的例子:

    file_interface = ('read', 'readline', 'seek')
    
    class InterfaceException(Exception): pass
    
    def implements_interface(obj, interface):
        d = dir(obj)
        for item in interface:
            if item not in d: raise InterfaceException("%s not implemented." % item)
        return True
    
    >>> import StringIO
    >>> s = StringIO.StringIO()
    >>> implements_interface(s, file_interface)
    True
    >>> 
    >>> fp = open('/tmp/123456.temp', 'a')    
    >>> implements_interface(fp, file_interface)
    True
    >>> fp.close()
    >>> 
    >>> d = {}
    >>> implements_interface(d, file_interface)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 4, in implements_interface
    __main__.InterfaceException: read not implemented.
    

        16
  •  0
  •   Jasmine Hegman    12 年前

    除了其他答案之外,我只想指出Javascript还有一个instanceof关键字,如果给定实例位于给定对象的原型链中的任何位置,则该关键字将返回true。

    这意味着,如果在“实现对象”的原型链中使用“接口对象”(这两个对象对JS来说都是纯对象),那么可以使用instanceof来确定它是否“实现”了它。这对强制方面没有帮助,但对多态性方面有帮助——多态性是接口的一个常见用途。

    MDN instanceof Reference

        17
  •  -2
  •   Geo    16 年前

    停止尝试用动态语言编写Java。