【问题标题】:Should I define interfaces in Duck Typed languages?我应该用 Duck Typed 语言定义接口吗?
【发布时间】:2011-01-21 23:59:05
【问题描述】:

我即将用鸭子类型语言 (Groovy) 编写我的第一个应用程序。

如果我要用静态类型语言编写相同的应用程序,那么我需要定义一些接口。显然,由于 Groovy 中的鸭子类型,它们实际上并不是必需的。目前,我认为将它们定义为需要在各种对象中实现的方法的文档可能是有意义的。我没有抓住重点吗?

【问题讨论】:

    标签: interface groovy duck-typing


    【解决方案1】:

    我最近一直在 SO 上阅读此内容(我现在找不到链接,但它是“为什么动态语言很好?”的帖子之一,以及 S. Lott 的一个重要回答很多cmets),答案是:

    你可以。特别是在 Groovy 中,您可以在 Java 或 Groovy 中定义接口并实现它们。然而,对于鸭子类型(Groovy 允许但也允许显式类型),许多人会说“为什么要麻烦?”源是它自己的文档,接口在源中,“使用源”等。

    就我个人而言,这让我发疯——我喜欢 Java 给我的编译时(或者实际上是开发时)检查,但这是另一个争论。如果您使用 Groovy,那是因为您想编写出自鸭式打字的精巧简洁明了的代码。在这种情况下,除非必要,否则应避免使用接口。

    它们在哪里是必要的?在程序的各个部分之间,以及在程序的公共 API 中(尽管它们也可以是抽象类)。 否则,我会说你应该尽量避免在鸭式语言中使用它们。这迫使您编写关于类的文档,或者编写非常清晰的代码,以致于它是同一件事。

    我认为这是一种糟糕的做法,但是这是向动态语言转变的范式的一部分。而且我认为,如果您避免将接口与实现充分分离,您就会理解其背后的“原因”。我仍然没有,尽管这与不重复代码(保持 DRY)有很大关系。

    编辑:从计算机中获得了一些清晰性:) 不将接口与实现分开的主要原因之一是您可以摆脱对类型的依赖.如您所知,在鸭子打字中,我不在乎它是否是Vehicle 接口的实现者(例如)。我只关心它是否有一个带有 2 个参数的 go 方法。因此,您使用接口的次数越多,您使用 Groovy 编写 Java 的次数就越多(“您可以用任何语言编写 Fortran”)。应该避免这种情况,因为新语言会让你接触到新事物。

    【讨论】:

    • @Martin,谢谢,我已经附加了我的答案以便更好地解释。
    【解决方案2】:

    我不熟悉 groovy,但总的来说,不,您不需要在松散类型的语言中定义接口。

    1. 您会重复自己,如果您需要更改方法签名,那么您需要在两个地方进行,而不是一个。

    2. 虽然接口确实可以用作文档,但在松散类型的语言中,大多数编码人员不会期望接口,因此如果他们需要文档,他们不会去搜索接口。

    3. 大多数动态语言都有很好的 IDE 可供它们使用,具有方法完成功能,这进一步减少了对单独接口的需求。

    4. 可以在动态语言中绑定和取消绑定方法。因此,您可以而且很可能最终会得到不符合接口的对象。拥有一个单独的界面最终可能会使阅读您的代码的人感到困惑。

    【讨论】:

    • @longshot 您使用什么 IDE/语言来实现良好的方法完成?我将 Netbeans 与 Ruby 一起使用,但它通常不知道有哪些方法可用,而只是从全局命名空间中完成它们。
    • Squeak smalltalk 有很好的方法完成和方法浏览器。 AllegroCL 对 Common Lisp 有很好的自动补全功能。 WingIDE 对 Python 有很好的自动补全功能,只要它知道你引用的是什么类型。 XCode 对 ObjC 有很好的补全,但同样需要知道您要向其发送消息的类型。
    • 和@S​​ergey Mirvoda,谢谢。 Objective-C 是我的新问题,所以我希望 XCode 能做到。
    【解决方案3】:

    定义接口是一种代码内文档。使用接口,您可以明确地声明您从类中期望满足您的需求。

    PS:groovy 不是我的语言,所以我实际上不知道是否可以在那里定义接口

    【讨论】:

      【解决方案4】:

      在某些情况下是的。我有一个示例,我正在创建一个 Groovy 类,该类由 Spring 注入到 Java 类中。我使用这样的泛型创建了一个接口:

      //interface injected to a java class
      public interface SomeInterface {
          <T> T getSomething(int version, Long id);
      }
      

      那么 groovy 的实现是这样的:

      //Groovy impelentation
      class SomeInterfaceImpl implements SomeInterface {
          def getSomething(int version, Long id) {
              //use duck typing to create similar objects based on version
          }
      }
      

      我的示例是我使用 JAXB 和 XJC 从 XML 模式创建对象并在 Jersey RESTful Web 服务中使用它们。我正在对 Web 服务进行版本控制,所做的更改足以进行版本控制,但仍有很多代码可以重用。使用接口被证明是有问题的,所以我改用 Groovy 并将所有类似的逻辑移到上面提到的带有鸭子类型的 Groovy 类中。这些对象大多是相同的,只是做了一些更改,因此使用 Java 类注入接口的鸭子类型可以完美地工作。

      【讨论】:

        猜你喜欢
        • 2011-08-28
        • 2012-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-19
        相关资源
        最近更新 更多