我如何只允许Ruby函数中的参数成为某种类型?

Orc*_*ris 3 ruby parameters arguments function

例如,如果我有

def function(arg)
  #do stuff
end
Run Code Online (Sandbox Code Playgroud)

我怎么只允许arg成为一个数组?我可以

def function(arg)
  if arg.class != 'Array'
    return 'Error'
  else
    #do stuff
  end
end
Run Code Online (Sandbox Code Playgroud)

但有没有更好的方法呢?

Sam*_*ane 8

你不能def function(Array arg)用其他语言做 ,但你可以用一个替换你的第二个片段的四行:

def function(arg)
  raise TypeError unless arg.is_a? Array
  # code...
end
Run Code Online (Sandbox Code Playgroud)


DGM*_*DGM 5

其他人已经指出如何在技术上强制执行某种类型的论点,但您正在与 ruby​​ 思维方式进行根本性的斗争。谷歌搜索“鸭子打字”。

在 ruby​​ 世界中,我们通常不担心参数的类型,而是它是否满足我们想要用它做的接口。换句话说,它像鸭子一样嘎嘎叫吗?够好了!

让我们假设您正在尝试使用 Array 来做某事:

def function(arg)
  arg.each do |a|
    puts a
  end
end
Run Code Online (Sandbox Code Playgroud)

如果你这样称呼它:function(1),你会得到NoMethodError: undefined method 'each'

让我们使用您将其强制为数组的想法。

def function(arg)
  raise TypeError unless arg.is_a? Array
  arg.each do |a|
    puts a
  end
end
Run Code Online (Sandbox Code Playgroud)

好的,现在我们犯了一个不同的错误,但是如果使用数组以外的其他东西调用该方法,它仍然会生成错误。

另外,这个怎么办?

function("Hello World".chars)
Run Code Online (Sandbox Code Playgroud)

哎呀,我们有一个错误,尽管该功能本来可以工作!

红宝石方式更像是:

def function(arg)
  if arg.respond_to? :each
    arg.each do |a|
      puts a
    end
  else
    puts arg
  end
end
Run Code Online (Sandbox Code Playgroud)

现在您的函数适用于各种输入:

function([1,2,3,4])
function("foo")
function("foo".chars)
Run Code Online (Sandbox Code Playgroud)

至于函数的正确性,您将使用测试进行介绍,而不是编译器。但那完全是另一回事。:)