はじめに:自作クラスで比較したいケース
自作クラスを簡単に比較したいケースがあると思います。
例えば、身長を格納するHeightクラスを作成したとします。
インスタンス化するときの式はこのようになります。
taro_height = Height.new(180)
そして、他の人と身長を比較したいケースが出てきたとします。
hanako_height = Height.new(158)
タロウさんとハナコさんの身長を簡単に比べるためには以下が出来ると嬉しいですよね。
taro_height > hanako_height
しかし、これを実現するにはモジュールのインポートと独自の実装が必要になります。
今回はテスト科目の点数を持つScoreクラスをサンプルコードとして扱っていき、比較可能にする方法を解説します。
自作クラスはそのままでは比較できない
まず、単純に自作クラスを作成して比較しようとしてみます。
サンプルコードをご覧ください。
class Score
def initialize(math, english, physics)
@math = math
@english = english
@physics = physics
end
end
score_noby = Score.new(30, 45, 50)
score_ace = Score.new(98, 95, 94)
puts score_noby < score_ace # undefined method `<'
puts score_noby > score_ace # undefined method `>'
puts score_noby == score_ace # false (Objectクラスの実装によりオブジェクトIDで比較される)
もちろん、このままでは比較演算子が使えません。
このままだとそのクラスの何を比較するのか、全く分からないですよね。
これを解消するには、Comparableモジュールをインクルードし、<=>メソッドを定義する必要があります。
比較する対象をきめる必要がある
比較する対象はテストの合計点としましょう。
そして、<=>メソッドを定義します。サンプルコードをご覧ください。
class Score
include Comparable # Comparableモジュールのインクルード
attr_reader :math, :english, :physics
def initialize(math, english, physics)
@math = math
@english = english
@physics = physics
end
def <=>(other)
if other.is_a?(Score)
@math + @english + @physics <=> other.math + other.english + other.physics
else
nil
end
end
end
score_noby = Score.new(30, 45, 50)
score_ace = Score.new(98, 95, 94)
puts score_noby < score_ace # > true
puts score_noby > score_ace # > false
puts score_noby == score_ace # > false
*nobyはのび太、aceは出木杉君の英名です。