我应该用鸭子类型语言定义接口吗?
我正准备用鸭子类型语言(Groovy)编写我的第一个应用程序。
如果我要用静态类型语言编写相同的应用程序,那么我需要定义一些接口。显然,由于 Groovy 中的鸭子类型,它们实际上并不是必需的。目前我认为将它们定义为需要在各种对象中实现的方法的文档可能是有意义的。我错过重点了吗?
I'm just about to write my first application in a duck typed language (Groovy).
If I was to write the same application in a static typed language then I would need to define some interfaces. Obviously because of the duck typing in Groovy they are not actually required. At the moment I am thinking that it might make sense to define them anyway as documentation of the methods that need to be implemented in the various objects. Am I missing the point?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我最近在 SO 上读到过这个问题(我现在找不到链接,但这是“为什么动态语言很好?”的帖子之一,也是 S. Lott 的一个大回答,有很多评论) ,答案是:
可以。特别是在 Groovy 中,您可以在 Java 或 Groovy 中定义接口并实现它们。然而,对于鸭子类型(Groovy 允许但也允许显式类型),许多人会说“为什么要麻烦呢?”源代码是它自己的文档,接口在源代码中,“使用源代码”等。
就我个人而言,这让我很生气——我喜欢 Java 给我的编译时(或者实际上是开发时)检查,但这就是另一场辩论。如果您使用 Groovy,那是因为您想编写来自鸭子类型的极其简洁和清晰的代码。在这种情况下,除非必要,否则应避免使用接口。
哪里需要它们?在程序的各个部分之间以及程序的公共 API 中(尽管它们也可以是抽象类)。 否则,我想说你应该在鸭子类型的语言中尽量避免使用它们。这迫使您编写有关类的文档,或者编写非常清晰的代码,以至于它们是同一件事。
我认为这是糟糕的做法,但是这是向动态语言范式转变的一部分。我认为,如果您充分避免将接口与实现分开,您就会理解其背后的“原因”。我仍然不这样做,尽管这与不重复代码(保持干燥)有很大关系。
编辑:远离计算机得到了一些清晰的信息:)不将接口与实现分开的主要原因之一是为了摆脱对类型的依赖。如您所知,在鸭子类型中,我不关心它是否是
Vehicle
接口的实现者(例如)。我只关心它是否有一个带有 2 个参数的go
方法。因此,您使用接口的次数越多,您在 Groovy 中编写 Java 的次数就越多(“您可以用任何语言编写 Fortran”)。应该避免这种情况,因为新语言会让你接触新事物。I've been reading on this recently here on SO (and I can't find the link right now, but it's one of those "why are dynamic languages good?" posts, and a big answer by S. Lott with many comments), and the answer is:
You could. In Groovy especially, you can define interfaces in Java or Groovy and implement them. However, with duck-typing (which Groovy allows but also allows explicit types) many people would say "why bother?" The source is it's own documentation, the interface is in the source, "use the source" etc.
Personally, this drives me mad -- I love the compile-time (or really, dev-time) checks Java gives me, but that's another debate. If you're using Groovy, it's because you want to write that brilliantly concise and clear code that comes from duck-typing. In that case, interfaces are to be avoided except where necessary.
Where are they necessary? Between parts of a program, and in the Public API for a program (though they can be abstract classes, too). Otherwise, I would say that you should try to avoid them in duck-typed languages. This forces you to write the docs on the classes, or write code that is so clear that it's the same thing.
I think this is terrible practice, HOWEVER this is part of the paradigm shift towards dynamic languages. And I think that if you avoid separating interface from implementation enough, you'll understand the 'why' behind it. I still do not, though it has a lot to do with not repeating code (keeping DRY).
Edit: Got some clarity away from the computer :) One of the main reasons NOT to separate interface from implementation is so that you move away from a dependence on types. In duck-typing, as you know, I don't care if it's an implementer of the
Vehicle
interface (for instance). I only care if it has ago
method with 2 params. So the more you work with interfaces, the more you are writing Java in Groovy ("you can write Fortran in any language"). This should be avoided, as new languages open you up to new stuff.我不熟悉 groovy,但一般来说,不,您不需要用松散类型语言定义接口。
您会重复自己,如果您需要更改方法签名,那么您需要在两个地方执行此操作,而不是一个地方。
虽然接口确实有一些作为文档的用途,但在松散类型语言中,大多数程序员不会期望接口,因此如果他们需要文档,就不会去搜索接口。
大多数动态语言都有良好的 IDE 可供使用,并且具有方法完成功能,这进一步减少了对单独接口的需求。
动态语言中的方法可以被绑定和解除绑定。因此,您可能而且可能会得到不遵守接口的对象。拥有单独的界面最终可能会让阅读代码的人感到困惑。
I'm not familiar with groovy, but in general, no, you don't need to define interfaces in loosely typed languages.
You would be repeating yourself, if you need to change a methods signature, then you need to do it in two places, not one.
Although interfaces do have some use as documentation, in a loosely typed language, most coders will not expect an interface, and therefore will not go searching for an interface if they need documentation.
Most dynamic languages have good IDE's available for them, with method completion, which further diminishes the need for a separate interface.
Methods can be bound and unbound in dynamic languages. Therefore, you can, and probably will, end up with objects that do not adhere to the interface. Having a separate interface could end up confusing people reading your code.
定义接口是一种代码内文档。通过接口,您可以显式声明您希望从类中得到什么来满足您的需求。
PS:groovy 不是我的语言,所以我实际上不知道是否可以在那里定义接口。
Defining an interface is a kind of in-code documentation. With an interface you declare explicitly what you expect from the class to satisfy your needs.
PS: groovy is not my language, so I actually don't know whether it's possible to define interfaces there at all.
在某些情况下是的。我有一个例子,我正在创建一个 Groovy 类,该类由 Spring 注入到 Java 类中。我使用如下泛型创建了一个接口:
然后 groovy 实现如下所示:
我的示例是,我使用 JAXB 和 XJC 从 XML 模式创建对象,并在 Jersey 的 Restful Web 服务中使用它们。我正在对 Web 服务进行版本控制,所做的更改足以进行版本控制,但仍然有很多代码可以重用。事实证明,使用接口是有问题的,因此我改用 Groovy,并将所有类似的逻辑通过鸭子类型转移到上述 Groovy 类中。这些对象大部分是相同的,但有一些变化,因此带有接口的鸭子类型可以完美地注入到 Java 类中。
In some cases yes. I have an example where I'm creating a Groovy class that gets injected into a Java class by Spring. I created an interface using generics like this:
Then the groovy implementation looks like this:
My example is that I'm using JAXB and XJC to create objects from an XML schema and using them in a Jersey restful web service. I'm versioning the web service and the changes are enough to version, but there's still a lot of code that can be reused. Using interfaces proved to be problematic, so I used Groovy instead and moved all the similar logic to the above mentioned Groovy class with duck typing. The objects are mostly the same with some some changes so duck typing with an interface to inject in the Java class works perfectly.