Menu
Coddy logo textTech

Comparable Modülü

Coddy'nin Ruby Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 29 / 57.

Ruby'nin yerleşik Comparable modülü, bir sınıfa <, <=, ==, >, >= operatörlerini ve between? ile clamp yöntemlerini sağlar. Sınıftan bir yönteme ihtiyaç duyar: Nesne küçük, eşit veya büyük olduğunda sırasıyla negatif bir sayı, 0 ya da pozitif bir sayı döndüren <=>:

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

Çıktı:

true
true
true

Sayılar ve dizeler zaten <=> operatörüne sahiptir; bu nedenle bir sınıf genellikle değerlerinden birine yetki verir. Dizileri karşılaştırmak, öğe öğe çalışır ve aynı anda birkaç alana göre sıralama yapar:

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

Çıktı:

true
true

sort, min ve max de <=> kullanır; bu nedenle sınıfın nesneleri bir blok olmadan sıralanabilir. clamp bir değeri diğer iki değer arasında tutar:

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

Çıktı:

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

<=>, diğer nesne karşılaştırılamıyorsa nil döndürmelidir. Ardından Comparable, kafa karıştırıcı bir NoMethodError ile başarısız olmak yerine < için ArgumentError yükseltir ve == için false döndürür:

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

  grams <=> other.grams
end

Weight.new(1) == 5     # false
Weight.new(1) < 5      # ArgumentError: Weight ile 5 karşılaştırması başarısız oldu
challenge icon

Görev

Kolay

Weight sınıfını tamamlayın. Weight.parse(text), 500g, 1.2kg veya 2lb değerlerini okur (1 lb, 453.6 g'dır) ve gram cinsinden saklar. Comparable'ı dahil edin ve gramlar üzerinde <=> tanımlayın. to_s, gramları 1200g örneğindeki gibi en yakın tam sayıya yuvarlanmış olarak döndürür.

Sağlanan kod, her giriş satırını ayrıştırır; ardından ağırlıkları sıralanmış olarak, en ağır olanı, en hafif olanı, ilk ağırlığın 1 kg ile 2 kg arasında olup olmadığını ve en fazla 1 kg olacak şekilde sınırlandırılmış ilk ağırlığı yazdırır.

Kodunuz weight.rb dosyasına gider. main.rb, sağlanan giriş/çıkış kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'weight'

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
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 iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Ruby derleyicisi