Menu
CoddyTech

module Comparable

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Ruby di Coddy. Pelajaran 29 dari 57.

module bawaan Ruby Comparable memberikan operator <, <=, ==, >, >= dan method between? serta clamp kepada sebuah class. Module ini memerlukan satu method dari class tersebut: <=>, yang mengembalikan angka negatif, 0, atau angka positif saat object lebih kecil, sama, atau lebih besar:

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))

Output:

true
true
true

Angka dan string sudah memiliki <=>, jadi class biasanya mendelegasikan perbandingan ke salah satu nilainya. Perbandingan array dilakukan elemen demi elemen, sehingga kamu bisa mengurutkan berdasarkan beberapa field sekaligus:

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

Output:

true
true

sort, min, dan max juga menggunakan <=>, sehingga object dari class ini bisa diurutkan tanpa blok. clamp menjaga nilai tetap di antara dua nilai lainnya:

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))

Output:

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

<=> seharusnya mengembalikan nil jika object lain tidak dapat dibandingkan. Comparable kemudian memunculkan ArgumentError untuk < dan mengembalikan false untuk ==, alih-alih gagal dengan NoMethodError yang membingungkan:

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

  grams <=> other.grams
end

Weight.new(1) == 5     # false
Weight.new(1) < 5      # ArgumentError: perbandingan Weight dengan 5 gagal
challenge icon

Tantangan

Mudah

Lengkapi class Weight. Weight.parse(text) membaca 500g, 1.2kg atau 2lb (1 lb adalah 453.6 g), lalu menyimpan berat dalam gram. Sertakan Comparable dan definisikan <=> berdasarkan gram. to_s mengembalikan jumlah gram yang dibulatkan ke bilangan bulat, seperti 1200g.

Kode yang disediakan memproses setiap baris input, lalu mencetak berat yang sudah diurutkan, berat terberat, berat teringan, apakah berat pertama berada di antara 1 kg dan 2 kg, serta berat pertama yang dibatasi hingga maksimal 1 kg.

Tulis kodemu di weight.rb. main.rb berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

require_relative 'weight'

# Kode input/output yang disediakan: biarkan apa adanya
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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Ruby online