LoginSignup
0
1

More than 1 year has passed since last update.

[Ruby] 自作クラスを比較可能にする方法

Last updated at Posted at 2021-10-04

:ledger: はじめに:自作クラスで比較したいケース

自作クラスを簡単に比較したいケースがあると思います。
例えば、身長を格納するHeightクラスを作成したとします。
インスタンス化するときの式はこのようになります。

taro_height = Height.new(180)

そして、他の人と身長を比較したいケースが出てきたとします。

hanako_height = Height.new(158)

タロウさんとハナコさんの身長を簡単に比べるためには以下が出来ると嬉しいですよね。

taro_height > hanako_height

しかし、これを実現するにはモジュールのインポートと独自の実装が必要になります。
今回はテスト科目の点数を持つScoreクラスをサンプルコードとして扱っていき、比較可能にする方法を解説します。

:ledger:自作クラスはそのままでは比較できない

まず、単純に自作クラスを作成して比較しようとしてみます。
サンプルコードをご覧ください。

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モジュールをインクルードし、<=>メソッドを定義する必要があります。

:ledger: 比較する対象をきめる必要がある

比較する対象はテストの合計点としましょう。
そして、<=>メソッドを定義します。サンプルコードをご覧ください。

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は出木杉君の英名です。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1