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

时间:2012-03-22 05:21:35

标签: ruby oop duck-typing

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

5 个答案:

答案 0 :(得分:20)

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

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

假设在main_routine中,假设each是一个数组,则使用arg1上的arg1方法。如果事实证明它是其他东西,未定义each,那么简单的错误消息将类似于method each not defined on ...,从方法的用户的角度来看{{1} ,可能没有帮助。在这种情况下,原始错误消息将被消息foo替换,这会更有帮助。

答案 1 :(得分:18)

Ruby当然是动态输入的。

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

如果来电者违反了此合同,则可能发生任何事情。该方法无需担心:它使用不正确。

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

单元测试可以帮助确保合同适用于预期数据。

答案 2 :(得分:9)

如果方法有理由存在,则会调用它。

如果写出合理的测试,一切都会被调用。

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

不要浪费时间进行可能不必要地限制来电者的类型检查,并且无论如何都会复制运行时检查。花时间编写测试。

答案 3 :(得分:1)

我建议在方法开头使用raise来添加手动类型检查,简单有效:

def foo(bar)
    raise TypeError, "You called foo without the bar:String needed" unless bar.is_a? String
    bar.upcase
end

当您没有太多参数时,最好的方法是,如果您有多个参数并注意其当前/未来的实施细节,建议使用ruby 2+上提供的关键字参数,他们正在改善这种情况,给出了程序员一种查看值是否为零的方法。

加:您可以使用自定义异常

class NotStringError < TypeError
   def message 
     "be creative, use metaprogramming ;)"
#...
raise NotStringError

答案 4 :(得分:1)

您可以使用Design by Contract方法,使用contracts ruby​​ gem。我发现它很不错。