我应该在Duck Typed语言中定义接口吗?

时间:2010-02-28 12:04:59

标签: interface groovy duck-typing

我正准备用鸭子式语言(Groovy)编写我的第一个应用程序。

如果我要用静态类型语言编写相同的应用程序,那么我需要定义一些接口。显然,由于在Groovy中打字,他们实际上并不需要。目前我认为将它们定义为有意义的是作为需要在各种对象中实现的方法的文档。我错过了这一点吗?

4 个答案:

答案 0 :(得分:13)

我最近在这里读过这篇文章(我现在找不到链接,但它是其中之一“为什么动态语言很好?”帖子,以及S. Lott的一个重要答案很多评论),答案是:

你可以。特别是在Groovy中,您可以在Java或Groovy中定义接口并实现它们。但是,使用duck-typing(Groovy允许但也允许使用显式类型),许多人会说“为什么要打扰?”源代码是它自己的文档,接口在源代码中,“使用源代码”等。

就个人而言,这让我很生气 - 我喜欢Java给我的编译时间(或真正的开发时间)检查,但这是另一场辩论。如果你正在使用Groovy,那是因为你想要编写那些来自鸭子类型的简洁明了的代码。在这种情况下,除非必要,否则应避免使用接口。

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

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

编辑:远离计算机有一些清晰度:)不将界面与实现分开的主要原因之一是让您摆脱对类型的依赖 。在鸭子打字中,如你所知,我不在乎它是否是Vehicle接口的实现者(例如)。我只关心它是否有{2}参数的go方法。因此,使用接口越多,您在Groovy中编写Java就越多(“您可以用任何语言编写Fortran”)。应该避免这种情况,因为新语言可以为您提供新的东西。

答案 1 :(得分:5)

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

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

  2. 虽然接口确实有一些用作文档,但是在松散类型的语言中,大多数编码器都不会期望接口,因此如果需要文档,则不会搜索接口。

  3. 大多数动态语言都有可用的IDE,方法完成,这进一步减少了对单独接口的需求。

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

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

//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,并将所有类似的逻辑移动到上面提到的带有duck typing的Groovy类。这些对象大部分都是相同的,但有一些变化,因此使用Java类中的注入接口进行的输入可以很好地工作。