あんまり面白くない例ですが,
[1, 2, 3].tails
を実行したときに,以下のような結果を返すtailsメソッドを追加する方法を考えます。
[[1, 2, 3], [2, 3], [3]]
クラスを再オープンする方法
class Array def tails ary = [] self.each_with_index do |ele, idx| ary << self[idx, self.length] end ary end end p [1, 2, 3].tails #=> [[1, 2, 3], [2, 3], [3]]
特異メソッドを利用する方法
この方法だと,aryだけにしかtailsメソッドは追加されません。
ary = [1, 2, 3] def ary.tails ary = [] self.each_with_index do |ele, idx| ary << self[idx, self.length] end ary end p ary.tails #=> [[1, 2, 3], [2, 3], [3]]
Mix-inを用いる方法
module Tails def tails ary = [] self.each_with_index do |ele, idx| ary << self[idx, self.length] end ary end end class Array include Tails end p [1, 2, 3].tails #=> [[1, 2, 3], [2, 3], [3]]
次に,Mix-inを使って,以下のようにArrayでもStringでもtailsメソッドが使えるようにしてみます。マルチバイト文字のことは考慮してません。
[1, 2, 3].tails #=> [[1, 2, 3], [2, 3], [3]] "abc".tails #=> ["abc", "bc", "c"]
each_with_indexは,Stringのインスタンスメソッドに含まれないので使えません。each_byteメソッドが使えそうですが,これはArrayのインスタンスメソッドに含まれません。ということで,whileを使って作ってみました。
module Tails def tails ary = [] idx = 0 len = self.length while idx < len ary << self[idx, len - idx] idx += 1 end ary end end class Array include Tails end p [1, 2, 3].tails #=> [[1, 2, 3], [2, 3], [3]] class String include Tails end p "abc".tails #=> ["abc", "bc", "c"]