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