Ruby程序员如何进行类型检查?

pyt*_*iku 23 ruby oop duck-typing

由于ruby中没有类型,Ruby程序员如何确保函数接收正确的参数?现在,我正在重复if object.kind_of/ instance_of语句检查并在任何地方引发运行时错误,这很难看.必须有更好的方法来做到这一点.

saw*_*awa 21

我个人的方式,我不确定它是否一般是推荐的方式,是在发生错误时进行类型检查并进行其他验证.我把类型检查程序放在救援区.这样,我可以在给出正确的参数时避免性能损失,但在发生错误时仍然会返回正确的错误消息.

def foo arg1, arg2, arg3
  ...
  main_routine
  ...
rescue
  ## check for type and other validations
  raise "Expecting an array: #{arg1.inspect}" unless arg1.kind_of?(Array)
  raise "The first argument must be of length 2: #{arg1.inspect}" unless arg1.length == 2
  raise "Expecting a string: #{arg2.inspect}" unless arg2.kind_of?(String)
  raise "The second argument must not be empty" if arg2.empty?
  ...
  raise "This is `foo''s bug. Something unexpected happened: #{$!.message}"
end
Run Code Online (Sandbox Code Playgroud)

假设,在假设这是一个数组时main_routine使用该方法.如果事实证明它是其他东西,没有定义,那么裸错误信息将是类似的,从方法的用户的角度来看,可能没有帮助.在这种情况下,原始错误消息将被消息替换,这更有帮助.eacharg1arg1eachmethod each not defined on ...fooExpecting an array: ...

  • 但问题是,由于拾取了其他问题之一,*real*错误可能会被掩盖.因此,虽然它可能*也是一个问题,但它可能与实际提出的内容无关.如果要进行显式类型检查,请先执行**,而不是恢复. (4认同)
  • 为什么使用`#{arg1}`而不是`#{arg1.inspect}`?或者更具体地说,"期待一个字符串:#{arg2}"而不是""期待一个字符串:#{arg2.inspect}"`? (2认同)
  • 我非常喜欢这个解决方案.对我来说,它看起来很优雅. (2认同)

小智 18

当然,Ruby是动态类型的.

因此,方法文档确定类型合同; 类型信息从正式类型系统移动到方法文档中的[非正式类型规范].我混合了诸如"像数组一样的行为"的普遍性和诸如"是一个字符串"之类的细节.调用者应该只期望使用所述类型.

如果来电者违反了这个合同,那么任何事情都可能发生.该方法不用担心:它使用不正确.

鉴于上述情况,我避免检查特定类型,并避免尝试使用此类行为创建重载.

单元测试有助于确保合同适用于预期数据.

  • @cjk虽然这是一个很好的范例,但它仍然没有回答这个问题.我建议你接受sawa的回答. (7认同)

Dig*_*oss 9

如果某个方法有理由存在,则会调用它.

如果编写合理的测试,将调用所有内容.

如果调用每个方法,那么每个方法都将进行类型检查.

不要浪费时间进行可能不必要地约束呼叫者的类型检查,并且无论如何都只会复制运行时检查.花那个时间写测试.