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