たとえば、私が持っている場合
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)
、2 番目のスニペットの 4 行を 1 行に置き換えることができます。
def function(arg)
raise TypeError unless arg.is_a? Array
# code...
end
あるタイプの引数を技術的に強制する方法を指摘する人もいますが、Ruby の考え方との根本的な戦いを戦っています。「ダックタイピング」でググってみてください。
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 は非常に柔軟な言語です。
例のレシーバーが自明であり、メソッドではなく関数のように定義されている場合は、引数をレシーバーに変換することをお勧めします。
class Array
def function
# do stuff
end
end
エラーを発生させる代わりに、引数を配列に変換することを確認できますが、最初に配列が得られるように、パラメーターを提供するルーチンで作業する必要があります。
def function(*arg)
a = arg.flatten
p a
end
function("ab")
function(1,2)
function([1,2])
#=>
#["ab"]
#[1, 2]
#[1, 2]