せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】オープンクラスの使い方、Arrayクラスの対称性

「>>メソッドを作ってみた」という記事を書かれたhp12cさんとの会話の中で

(せ)
「>>」メソッドのレシーバーはArrayクラスオブジェクトである必要はないのでは?

と書いて、Objectクラスにオーバーライドする形で例を作ってみたところ、
 

(h)
さすがにObject#>>はすべてのクラスに継承してしまうので、まずいでしょうねー。難しいですね。

と指摘を頂いた。
なるほど。そりゃそうだ。
 
 
 

オープンクラスの使い方

普通はどうするのかな、と思って既存の実装を確認してみた。
たとえばgem「mail」では、こんな形でObjectクラスをオーバーライドしている。

unless Object.method_defined? :blank?
  class Object
    def blank?
      if respond_to?(:empty?)
        empty?
      else
        !self
      end
    end
  end
end

なるほど。
定義されていないときにだけ「>>」メソッドを追加するようにすれば
既存のメソッドに影響はない。
hp12cさん、どうですかね?

 

Arrayクラスのメソッド対称性

同じくhp12cさんとの会話の中で

(せ)
shift とunshift 自体も対称的ではないのですね。
shift は引数に数値を持つけど、unshift は引数が挿入したい要素の可変長引数。
(h)
対称性はpushとunshift(挿入系)、popとshift(抜去系)で取れていればいい

とのこと。
 
ふむふむ?なるほど?!
Arrayクラスはメソッドがたくさんあって、いまいち使いこなせていないのは、
メソッドをパターン化して理解出来ていないからかも。
このタイミングで勉強しなおしてみる。

arr = [1,2,3,4]
arr.push("aa").pop 
p arr #=>[1,2,3,4]
arr.unshift("bb").shift
p arr  #=>[1,2,3,4]
arr.push(arr.pop)
p arr  #=>[1,2,3,4]
arr.unshift(arr.shift)
p arr  #=>[1,2,3,4]

なるほど、対称性っていうのはメソッドの形云々ではないのか。
こうやって見ると、対になってはいるものの、非可換だ。

勉強になりました。