Menu
Coddy logo textTech

Comparable 모듈

Coddy Ruby 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 29번째.

Ruby의 내장 모듈 Comparable은 클래스에 연산자 <, <=, ==, >, >=와 메서드 between? 및 clamp를 제공합니다. 이 모듈을 사용하려면 클래스에 있는 다음 메서드 하나가 필요합니다: <=>. 이 메서드는 객체가 더 작거나, 같거나, 더 클 때 각각 음수, 0 또는 양수를 반환합니다.

class Weight
  include Comparable
  attr_reader :grams

  def initialize(grams)
    @grams = grams
  end

  def <=>(other)
    grams <=> other.grams
  end
end

a = Weight.new(500)
b = Weight.new(1200)
puts a < b
puts a == Weight.new(500)
puts b.between?(a, Weight.new(2000))

출력:

true
true
true

숫자와 문자열에는 이미 <=>가 있으므로, 클래스는 보통 해당 값 중 하나에 비교를 위임합니다. 배열 비교는 요소별로 수행되므로 여러 필드를 한 번에 기준으로 정렬할 수 있습니다:

class Person
  include Comparable
  attr_reader :last, :first

  def initialize(first, last)
    @first = first
    @last = last
  end

  def <=>(other)
    [last, first] <=> [other.last, other.first]
  end
end

a = Person.new("Ada", "Lovelace")
b = Person.new("Alan", "Turing")
c = Person.new("Byron", "Lovelace")
puts a < c
puts b > c

출력:

true
true

sort, min 및 max도 <=>를 사용하므로 블록 없이도 이 클래스의 객체를 정렬할 수 있습니다. clamp는 값을 두 다른 값 사이에 유지합니다:

class Weight
  include Comparable
  attr_reader :grams

  def initialize(grams)
    @grams = grams
  end

  def <=>(other)
    grams <=> other.grams
  end

  def to_s
    "#{grams}g"
  end
end

list = [Weight.new(900), Weight.new(150), Weight.new(400)]
puts list.sort.join(", ")
puts list.max
puts Weight.new(5000).clamp(Weight.new(0), Weight.new(1000))

출력:

150g, 400g, 900g
900g
1000g

<=>는 다른 객체를 비교할 수 없을 때 nil을 반환해야 합니다. 그러면 Comparable은 <에 대해 ArgumentError를 발생시키고 ==에 대해서는 false를 반환하므로, 이해하기 어려운 NoMethodError로 실패하지 않습니다:

def <=>(other)
  return nil unless other.is_a?(Weight)

  grams <=> other.grams
end

Weight.new(1) == 5     # false
Weight.new(1) < 5      # ArgumentError: Weight와 5의 비교가 실패했습니다
challenge icon

챌린지

쉬움

Weight 클래스를 완성하세요. Weight.parse(text)는 500g, 1.2kg 또는 2lb(1 lb는 453.6 g)를 읽고 그램 단위로 저장합니다. Comparable을 포함하고 그램을 기준으로 <=>를 정의하세요. to_s는 그램을 정수로 반올림한 값을 반환합니다. 예를 들면 1200g과 같습니다.

제공된 코드는 각 입력 줄을 파싱한 다음, 정렬된 무게, 가장 무거운 무게, 가장 가벼운 무게, 첫 번째 무게가 1 kg과 2 kg 사이에 있는지 여부, 그리고 최대 1 kg으로 제한된 첫 번째 무게를 출력합니다.

코드는 weight.rb에 작성하세요. main.rb에는 제공된 입력/출력 코드가 들어 있으며 수정할 수 없습니다.

직접 해보기

require_relative 'weight'

# 제공된 입력/출력 코드: 있는 그대로 유지하세요
input = []
while (line = gets)
  input << line.chomp
end
weights = input.map { |line| Weight.parse(line) }
puts "sorted: #{weights.sort.join(", ")}"
puts "heaviest: #{weights.max}"
puts "lightest: #{weights.min}"
puts "first between 1kg and 2kg: #{weights[0].between?(Weight.parse("1kg"), Weight.parse("2kg"))}"
puts "first clamped: #{weights[0].clamp(Weight.parse("0g"), Weight.parse("1kg"))}"
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Ruby 컴파일러