由于Ruby没有类型,Ruby程序员如何确保函数收到正确的参数?现在,我正在重复If ocket.kind_of/instance_of语句以检查和提高运行时

问题描述 投票:0回答:6
instance_of

语句,以检查并在各处增加运行时错误,这很丑陋。必须有更好的方法。

	
我的个人方式(我不确定这是否是建议的方式)是在发生错误后进行类型检查并进行其他验证。我将类型的检查例程放在救援块中。这样,当给出正确的参数时,我可以避免绩效丧失,但是在发生错误时仍会退还正确的错误消息。
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

ruby oop duck-typing
6个回答
24
投票
中,您可以在

each

上使用该方法
arg1
假设

arg1

是一个数组。如果事实证明它是其他的,而不是定义
each
,则裸露的错误消息将是类似
method each not defined on ...
,从方法的使用者的角度来看,这可能不是有帮助。在这种情况下,原始错误消息将被消息
foo
替换,这更有帮助。
    
当然,ruby是动态键入的。

方法文档确定类型合同;类型信息从正式的类型系统转移到[方法文档中的非正式类型规范。我将诸如“阵列”和“是字符串”之类的细节之类的概述混合在一起。呼叫者只能期望与
stated类型一起使用。

如果呼叫者违反了此合同,那么任何事情都可能发生
。该方法不必担心:它被错误地使用。
在上述情况下,iAvoid
检查特定类型,并试图以这种行为来创建过载。 lunit检验可以确保合同适用于预期数据。


19
投票
如果方法有理由存在,则将被称为。

如果编写了合理的测试,则所有内容都将被称为。

如果每个方法都被调用,则每个方法都会被键入检查。

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

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

Expecting an array: ...

当您没有太多参数时,最好的方式也建议是使用Ruby 2+上可用的关键字参数,如果您有多个参数,请注意其当前/将来的实现详细信息,它们正在改善情况,从而为程序员提供一个查看该值是否为nil。

加:您可以使用自定义异常 def foo(bar) raise TypeError, "You called foo without the bar:String needed" unless bar.is_a? String bar.upcase end

您可以使用contracts方法使用theContractsRubyGem进行设计。我觉得很好。


9
投票

使用手动类型检查

您可以手动检查参数的类型并在错误的情况下引起错误。

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


2
投票

用鸭子打字

启用检查特定类别,您可以检查对象是否响应所需的方法。

raise

使用Ruby 3的类型签名(RB)

1
投票

RBS文件中的定义类型(.rbs): def my_method(param) raise TypeError, "Expected String, got #{param.class}" unless param.is_a?(String) puts "Valid input: #{param}" end my_method("Hello") # Works fine my_method(123) # Raises: TypeError: Expected String, got Integer


0
投票
Sorbet是第三方静态型检查器。
  1. respond_to?

    参考:

    https://sorbet.org/
https://github.com/sorbet/sorbet
  1. 使用is_a?还是响应_to?用于运行时类型检查。
    
    使用Ruby 3的RB用于静态执行。

    使用更严格的运行时类型检查。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.