在Ruby中,什么与C#中的接口等效?
我目前正在尝试学习Ruby,并试图更多地了解它在封装和契约方面提供的功能 在C#中,可以使用接口定义合同。实现接口的类必须通过为定义的每个方法和属性(可能还有其他东西)提供实现来满足合同中的条款。实现接口的单个类可以在契约定义的方法范围内执行任何需要的操作,只要它接受相同类型的参数并返回相同类型的结果 有没有办法在Ruby中实现这种功能 谢谢 我在C#中的意思的一个简单示例:在Ruby中,什么与C#中的接口等效?,c#,ruby,interface,contract,equivalent,C#,Ruby,Interface,Contract,Equivalent,我目前正在尝试学习Ruby,并试图更多地了解它在封装和契约方面提供的功能 在C#中,可以使用接口定义合同。实现接口的类必须通过为定义的每个方法和属性(可能还有其他东西)提供实现来满足合同中的条款。实现接口的单个类可以在契约定义的方法范围内执行任何需要的操作,只要它接受相同类型的参数并返回相同类型的结果 有没有办法在Ruby中实现这种功能 谢谢 我在C#中的意思的一个简单示例: ruby中没有接口,因为ruby是一种动态类型化语言。接口基本上用于在不破坏类型安全的情况下使不同的类可互换。您的代码可
ruby中没有接口,因为ruby是一种动态类型化语言。接口基本上用于在不破坏类型安全的情况下使不同的类可互换。您的代码可以与每个控制台一起工作,只要它的行为类似于一个控制台,在C#中意味着实现IConsole。“duck typing”是一个关键字,您可以使用它来跟上动态语言处理此类问题的方式
此外,您可以而且应该编写单元测试来验证代码的行为。每个对象都有一个
respond\u to?
方法,可以在断言中使用。Ruby实际上没有它们;接口和契约通常更多地生活在静态世界中,而不是动态世界中
如果您真的需要,有一个名为gem的工具可以实现非正式契约。Ruby使用模块的概念作为接口的替代(类似)。Ruby中的设计模式有很多非常好的例子,说明了这两个概念之间的差异,以及Ruby为什么选择更灵活的接口替代方案
接口通常被引入到静态类型的OO语言中,以弥补多重继承的不足。换句话说,它们更多的是一种必要的邪恶,而不是有用的东西本身 另一方面,Ruby:
foo
,它们既不需要继承相同的祖先类,也不需要实现相同的接口接口的概念混为一谈,接口是一个抽象的单元职责、保证和协议规范,而接口是Java、C#和VB.NET编程语言中的一个关键字。在Ruby中,我们一直使用前者,但后者根本不存在
区分两者是非常重要的。重要的是界面,而不是界面
。界面
告诉您几乎没有什么有用的东西。没有什么比Java中的marker接口更能说明这一点,Java中的marker接口是完全没有成员的接口:只需看看和;这两个interface
s的含义非常不同,但它们具有完全相同的签名
那么,如果两个接口
具有相同的签名,那么接口
到底是什么
另一个好例子:
interface ICollection<T>: IEnumerable<T>, IEnumerable
{
void Add(T item);
}
另一个例子:它实际上在哪里说,你知道,它是一个集合?哪儿也没有!或者更准确地说,在文档中。用英语
在Java和.NET中几乎所有的接口
,所有相关信息实际上都在文档中,而不是在类型中。那么,如果这些类型没有告诉你任何有趣的事情,为什么还要保留它们呢?为什么不坚持使用文档呢?这正是Ruby所做的
请注意,还有其他一些语言,可以用这些语言对接口进行有意义的描述。但是,这些语言通常不调用描述接口的构造“Interface
”,而是将其称为type
。例如,在依赖类型的编程语言中,您可以表示以下属性:sort
函数返回与原始元素长度相同的集合,原始元素中的每个元素也在已排序的集合中,并且较小的元素之前不出现较大的元素
因此,简而言之:Ruby没有与Java接口
等价的接口。然而,它确实有一个与Java接口等价的接口,它与Java:documentation中的接口完全相同
此外,与Java一样,验收测试也可用于指定接口
特别是,在Ruby中,对象的接口取决于它能做什么,而不是类是什么,或者它混合了什么模块。任何具有Jorg的对象都有一个优点,ruby有接口,而不是关键字。在阅读一些回复时,我认为这在动态语言中是负面的。您必须创建单元测试,而不是让编译器捕获未实现的方法,而不是通过该语言强制执行接口。这也使得理解方法更难推理,因为当你们试图调用它时,你们必须找出一个对象是什么
例如:
def my_func(options)
...
end
如果您查看函数,您不知道什么是选项以及它应该调用什么方法或属性,而不查找单元测试、调用它的其他位置,甚至不查看方法。更糟糕的是,该方法甚至可能不使用这些选项,而是将其传递给其他方法。为什么要编写单元测试,而这本应该被编译器捕获。问题是您必须以不同的方式编写代码,才能用动态语言表达这种缺点
不过,这有一个好处,那就是动态编程语言编写代码的速度很快。我不知道
class MyCollection<T>: ICollection<T>
{
void Add(T item)
{
Remove(item);
}
}
def my_func(options)
...
end