Ruby 与任何其他语言一样具有接口。
请注意,您必须小心不要将 接口 的概念混为一谈,它是一个单元的职责、保证和协议的抽象规范,与 interface 的概念相混淆。是 Java、C# 和 VB.NET 编程语言中的关键字。在 Ruby 中,我们一直使用前者,但后者根本不存在。
区分两者非常重要。重要的是接口,而不是interface。 interface 告诉您几乎没有任何用处。没有什么比 Java 中的 标记接口 更能说明这一点了,它们是完全没有成员的接口:看看 java.io.Serializable 和 java.lang.Cloneable;这两个interfaces 意味着非常不同的东西,但它们具有完全相同的签名。
那么,如果两个 interfaces 意味着不同的东西,具有相同的签名,那么 interface 到底是什么?
另一个很好的例子:
package java.util;
interface List<E> implements Collection<E>, Iterable<E> {
void add(int index, E element)
throws UnsupportedOperationException, ClassCastException,
NullPointerException, IllegalArgumentException,
IndexOutOfBoundsException;
}
java.util.List<E>.add的接口是什么?
- 集合的长度不会减少
- 之前集合中的所有项目仍然存在
-
element 在集合中
其中哪些实际上出现在interface 中?没有! interface 中没有任何内容表明 Add 方法甚至必须添加,它也可以从集合中删除一个元素。 p>
这是interface 的一个完全有效的实现:
class MyCollection<E> implements java.util.List<E> {
void add(int index, E element)
throws UnsupportedOperationException, ClassCastException,
NullPointerException, IllegalArgumentException,
IndexOutOfBoundsException {
remove(element);
}
}
另一个例子:在java.util.Set<E> 中,它实际上在哪里说它是一个集合?无处!或者更准确地说,在文档中。英文。
在几乎所有interfaces 的情况下,无论是来自Java 还是.NET,所有相关 信息实际上都在文档中,而不是在类型中。所以,如果这些类型无论如何都不能告诉你任何有趣的事情,为什么还要保留它们呢?为什么不只关注文档?而这正是 Ruby 所做的。
请注意,其他语言实际上可以用有意义的方式描述接口。但是,这些语言通常不会将描述接口的构造称为“interface”,而是将其称为type。例如,在依赖类型的编程语言中,您可以表达以下属性:sort 函数返回与原始集合长度相同的集合,原始中的每个元素也在排序集合中,并且较小的元素之前不会出现较大的元素。
因此,简而言之:Ruby 没有与 Java interface 等效的对象。但是,它确实具有与 Java Interface 等价的功能,并且与 Java 中的文档完全相同。
此外,就像在 Java 中一样,验收测试也可用于指定接口。
特别是,在 Ruby 中,对象的 接口 取决于它可以做什么,而不是 class 是什么,或者 module 它是什么混入。任何具有<< 方法的对象都可以附加到。这在单元测试中非常有用,您可以简单地传入Array 或String 而不是更复杂的Logger,即使Array 和Logger 不共享显式interface因为他们都有一个名为<<的方法。
另一个例子是StringIO,它实现了与IO相同的接口,因此File的大部分接口,但不共享任何除了Object之外的共同祖先。