例如,如果我有
def function(arg)
#do stuff
end
我如何只允许arg
成为一个数组?我可以做
def function(arg)
if arg.class != 'Array'
return 'Error'
else
#do stuff
end
end
但是有没有更好的方法呢?
例如,如果我有
def function(arg)
#do stuff
end
我如何只允许arg
成为一个数组?我可以做
def function(arg)
if arg.class != 'Array'
return 'Error'
else
#do stuff
end
end
但是有没有更好的方法呢?
您不能 def function(Array arg)
像其他语言那样做,但是您可以将第二个代码段的四行替换为一行:
def function(arg)
raise TypeError unless arg.is_a? Array
# code...
end
其他人指出了如何在技术上强制执行某种类型的论点,但你正在与红宝石思维方式进行一场根本性的战斗。谷歌搜索“鸭子打字”。
在 ruby 世界中,我们通常不关心参数的类型,而是关心它是否满足我们想要用它做的接口。换句话说,它像鸭子一样嘎嘎叫吗?够好了!
假设您正在尝试将 Array 用于某事:
def function(arg)
arg.each do |a|
puts a
end
end
如果你这样称呼它:function(1)
,你会得到NoMethodError: undefined method 'each'
让我们使用您将其强制为数组的想法。
def function(arg)
raise TypeError unless arg.is_a? Array
arg.each do |a|
puts a
end
end
好的,现在我们犯了一个不同的错误,但是如果使用数组以外的东西调用该方法,它仍然会产生错误。
此外,这个呢?
function("Hello World".chars)
哎呀,我们有一个错误,尽管该功能可以工作!
红宝石方式更像是:
def function(arg)
if arg.respond_to? :each
arg.each do |a|
puts a
end
else
puts arg
end
end
现在您的函数适用于各种输入:
function([1,2,3,4])
function("foo")
function("foo".chars)
至于函数的正确性,您使用测试而不是编译器来覆盖它。但那完全是另一回事了。:)
很好地考虑到 Ruby 是动态类型的,您不能以类似的方式强制执行它,例如在 C 中。您实际上可以将它与类进行比较,而不是与字符串进行比较。
arg.is_a?(Array)
为了改进你的例子,我会写:
def function(arg)
raise TypeError unless arg.is_a?(Array)
# Do stuff
end
Ruby 不支持类型检查——至少,不能将参数类型声明为方法签名的一部分。一般来说,调用者负责传递正确的对象,或者传递的对象负责转换自己。但是,您当然可以进行自己的强制。事实上,about.com 有一个使用 case 语句进行这种类型检查的示例。
以下是一些额外的例子:
# Ask your object to convert itself to an array.
def foo my_object
my_object.to_a
end
# Give your object a #to_a method if it doesn't already have one.
def foo my_object
unless my_object.respond_to? :to_a
def my_object.to_a
# perform your type conversion
end
end
end
# Do your own type conversions.
def foo my_object
case my_object
when Array
p my_object
when String
my_object.scan /\d+/
end
end
您可以混合和匹配这些技术中的任何一种,当然还有其他技术。Ruby 是一种非常灵活的语言。
您可以确定将参数转换为数组,而不是引发错误,但您应该在提供参数的例程中工作,以便它首先为您提供数组。
def function(*arg)
a = arg.flatten
p a
end
function("ab")
function(1,2)
function([1,2])
#=>
#["ab"]
#[1, 2]
#[1, 2]
如果您的示例中的接收器是微不足道的,并且它被定义为函数而不是方法,那么您可能希望将参数转换为接收器。
class Array
def function
# do stuff
end
end