Rubyを記述しているときにメソッドに単体でも配列でもどっちでも渡せたらと思うときはありませんか?
そんなときはKernel#Arrayを使うと便利です。
以下のprint_nameというメソッドをサンプルに考えてみます。
Fruitクラスを渡して、フルーツの名前を表示する簡単なメソッドです。
class Fruit
attr_reader :name
def initialize(name)
@name = name
end
end
def print_name(fruit)
puts fruit.name
end
print_name(Fruit.new("Banana"))
出力結果
Banana
フルーツが複数ある場合を考えてみる
先程の例ではフルーツが1つでしたが、複数になった場合を考えてみます。
複数のフルーツの名前を表示したいと思ったら、以下のようなコードを書くのではないでしょうか?
def print_name(fruit)
puts fruit.name
end
# print_nameをFruitがあるだけ書きまくる
print_name(Fruit.new("Banana"))
print_name(Fruit.new("Apple"))
# もしくは配列にしてループする
[Fruit.new("Banana"), Fruit.new("Apple")].each do |fruit|
print_name(fruit)
end
もしくは、print_nameメソッドの中でループさせてもできそうです。
def print_name(fruits)
fruits.each do |fruit|
puts fruit.name
end
end
print_name([Fruit.new("Banana")])
print_name([Fruit.new("Banana"), Fruit.new("Apple")])
どちらでも、複数のフルーツの名前を表示できますが、
Fruitクラスのインスタンス単体もしくはFruitクラスのインスタンスの配列のどちらかを渡さないとメソッドが機能しません。
もっと柔軟にどちらを渡しても機能するようにできないのでしょうか?
Kernel#Arrayを使えば単体でも配列でも機能するようにできる
こういうときにKernel#Arrayを使うと引数が単体でも配列でも機能するメソッドを書くことができます。
def print_name(fruits)
fruits = Array(fruits)
fruits.each do |fruit|
puts fruit.name
end
end
print_name(Fruit.new("Banana"))
print_name([Fruit.new("Banana"), Fruit.new("Apple")])
Kernel#Arrayの動作をいくつか見てみます。
Array(nil) #=> []
Array([]) #=> []
Array(1) #=> [1]
Array([1]) #=> [1]
Array([1, 2]) #=> [1, 2]
Array([[1, 2]]) #=> [[1, 2]]
Array([[1, 2], [3, 4]]) #=> [[1, 2], [3, 4]]
ドキュメントによると、
to_ary、to_aの順で呼び出し、戻ってきた配列を返す。
また、どちらも定義されていない場合は指定した引数を配列にしたものを返すようです。
https://docs.ruby-lang.org/ja/latest/method/Kernel/m/Array.html
まとめ
Kernel#Arrayを使えば単体、配列どちらでも渡せる柔軟性のあるメソッドを記述できるので便利です。
気になる人は使ってみてください。
あと、これは余談ですが、
Kernel#Arrayはなぜ"A"rrayなのでしょうね?
Rubyのメソッドは一般的に小文字スタートだと思っているのですが・・・
気になるところです。
それではまた。
TomoProg