Ruby中类型的约定是什么?

Ruby中类型的约定是什么?,ruby,typing,design-documents,Ruby,Typing,Design Documents,由于Ruby是一种纯动态类型的语言,我一直不确定我应该对传递给我的方法的类型有什么期望。例如,如果我的方法只在传递整数时才起作用,那么我应该主动检查以确保是这样,还是应该在这种情况下允许类型异常 此外,当涉及到围绕Ruby代码编写设计文档时,指定方法应操作的类型的正确方法是什么?例如,Javadocs(虽然通常不用于设计文档)确切地指定了方法将操作的类型,因为语言本身是静态类型的,但是Ruby文档似乎始终对方法的前置和后置条件非常不精确。在Ruby中是否有指定这种格式的标准实践?有趣的问题 类型

由于Ruby是一种纯动态类型的语言,我一直不确定我应该对传递给我的方法的类型有什么期望。例如,如果我的方法只在传递整数时才起作用,那么我应该主动检查以确保是这样,还是应该在这种情况下允许类型异常

此外,当涉及到围绕Ruby代码编写设计文档时,指定方法应操作的类型的正确方法是什么?例如,Javadocs(虽然通常不用于设计文档)确切地指定了方法将操作的类型,因为语言本身是静态类型的,但是Ruby文档似乎始终对方法的前置和后置条件非常不精确。在Ruby中是否有指定这种格式的标准实践?

有趣的问题

类型安全 Java和Ruby几乎截然相反。 在Ruby中,您可以执行以下操作:

String = Array
# warning: already initialized constant String
p String.new
# []
因此,您几乎可以忘记从Java知道的任何类型安全性

对于第一个问题,您可以:

  • 确保调用该方法时使用的不是整数(例如
    my\u方法(array.size)
  • 接受该方法可能会被浮点、整数或有理数调用,并且可能会对输入调用
    to_i
  • 使用能够很好地处理浮点数的方法:例如
    (1..3.5)。to_a#=>[1,2,3]
    'a'*2.5#=>'aa'
  • 如果用其他方法调用它,您可能会得到一个
    NoMethodError:undefined方法“to_i”for object…
    ,您可以尝试处理它(例如,使用
    rescue
文档 记录方法的预期输入和输出的第一步是在正确的位置(类或模块)定义方法,并使用适当的方法名称:

  • 是否为素数?
    应返回布尔值
  • 是素数吗?
    应在中定义
否则,支持文档中的类型:

# @param [Array<String, Symbol>] arg takes an Array of Strings or Symbols
def foo(arg)
end
#@param[Array]arg接受字符串或符号数组
def foo(arg)
结束

我不确定为什么只要求将整数传递到方法中,但我不会在整个代码中主动检查该值是否为整数。例如,如果您正在执行需要整数的算术,我会在需要的位置键入或将值转换为整数,并通过注释或在方法头中解释这样做的目的

在我看来,这是基于观点的。并且在很大程度上取决于上下文和您的需求。问问你自己:我在乎吗?可以提出错误吗?用户是谁(我的代码与外部客户)?我能处理并修复输入吗

我认为一切都很好,因为不在乎(可能会引起奇怪的例外)

过度使用鸭式检查

或者只是将其转换为例外类型

要预先检查类型(并引发有用的异常),请执行以下操作:


这实际上取决于您的需要以及所需的安全级别。

您需要注意的第一件事是类和类型之间的区别

非常不幸的是,Java混淆了这一区别,因为类总是类型(尽管Java中还有其他类型不是类,即接口、原语和泛型类型参数)。事实上,几乎每本关于Java风格的书都会告诉您不要使用类作为类型。此外,William R.Cook在其关于理解数据抽象的开创性论文《重温》中指出,在Java中,类描述的是抽象数据类型,而不是对象。接口描述对象,所以如果在Java中使用类作为类型,就不是在做OO;如果您想在Java中实现OO,那么唯一可以作为类型使用的是接口,唯一可以使用类作为工厂

在Ruby中,类型更像是网络协议:类型描述对象理解的消息以及它对这些消息的反应。(这种相似性绝非偶然:Ruby的远祖Smalltalk的灵感来自后来的互联网。用Smalltalk的话说,“协议”是非正式用于描述对象类型的术语。在Objective-C中,这种非正式的协议概念是语言的一部分,而主要受Objective-C影响的Java直接复制了这个概念,但将其重命名为“接口”。)

因此,在Ruby中,我们有:

  • 模块
    (一种语言功能):代码共享和差异化实现的工具;不是一种类型
  • (一种语言功能):对象的工厂,也是一个
    模块
    ,不是一种类型
  • 协议(一种非正式的东西):对象的类型,以消息的响应和响应方式为特征

还要注意,一个对象可以有多个类型。例如,字符串对象具有类型“可追加的”(如果我的方法仅在传递整数时才起作用,则响应
)-极不可能;-)阅读有关Duck类型的信息;搜索“ruby duck类型”。不要期望一个整数,期望一些知道如何像整数一样工作的东西,也许可以通过看看它是否知道
to_i
。答案很好!但是,我们必须找到一个反例:
Float::INFINITY.to_i
/
Float::INFINITY.to_int
-)
def add(a, b)
  a + b # raise NoMethodError if a does not respond_to +
end
def add(a, b)
  if a.respond_to?(:+)
     a + b
  else
     "#{a} #{b}" # might makes sense?
  end
end 
def add(a, b)
  a.to_i + b.to_i
end
def integers(a, b)
  raise ArgumentError, "args must be integers" unless a.is_a?(Integer) and b.is_a?(Integer)
  a + b
end