webエンジニアの日常

RubyやPython, JSなど、IT関連の記事を書いています

あっ!UFO演算子!Comparableモジュールの実装方法をご紹介します。

Effective Rubyの勉強メモです。

13章はUFO演算子とComparableモジュールについてです。

この二つは以前記事にしたことがあるのでササっと流していきます。

www.uosansatox.biz

簡単に言うと、UFO演算子(<=>)を定義するだけでsortやminメソッドが使えるようになります。

UFO演算子は自由に実装していいわけではなく、次のルールを守る必要があります。

  • 比較できないときはnilを返す

  • レシーバ(演算子の左側)が小さいときは-1を返す

  • 逆にレシーバが大きいときは1を返す

  • 等しいときは0を返す

何をもって大きい小さい等しいのかは自分で決める必要があります。

スポンサーリンク

また、UFO演算子に加えて、Comparableモジュールをインクルードすればインスタンス同士の大小等(<, >, <=, >=, ==)比較ができるようになります。

ここまでが以前の記事の内容ですが、さらにもう少し付け加えます。

Comarableモジュールで提供されている"=="よりも独自で等値を定義した方がいい場合もあります。

例えばFixnumクラスでは1 == 1.0がtrueとなるように等値の処理に型変換が挟まっています。

独自に等値を定義するには、==演算子を再定義するか、<=>演算子の0が返る条件を変更するかです。

<=>の定義を変更する場合には等値だけでなく、<=, >=にも影響が出るため、比較演算子に一貫性が必要無ければ<=>の定義を変更しても問題ないですが、そうでなければ==をオーバーライドするのがよいです。

もう一つ、UFO演算子とComparableモジュールをインクルードしたクラスのインスタンスをハッシュのキーに使いたい場合、12章でも書きましたが、eql?メソッドとhashメソッドを定義する必要があります。

www.uosansatox.biz

eql?メソッドはデフォルトでequal?メソッドと同じくobject_idが同じ場合のみ等しいとするのでした。

そこでeql?メソッドは内部で==演算子で比較するように実装しておきます。

def eql?(other)
  self == other
end

としてもいいですが、別名にしてしまっても問題ないです、

alias_method(:eql?, :==)

hashメソッドは異なるオブジェクトは異なるハッシュ値を返すようにしなければならないので、インスタンス変数に委譲してしまうのが簡単です。

def hash
  name.hash
end

nameというインスタンス変数がある場合はこんな感じです。

Effective Ruby

Effective Ruby

Ruby on Rails 5アプリケーションプログラミング

Ruby on Rails 5アプリケーションプログラミング