Menu
CoddyTech

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 <, <=, ==, >, >= işleçlerini ve between? ile clamp metotlarını sağlar. Sınıftan bir metoda ihtiyaç duyar: Nesne daha küçük, eşit veya daha büyük olduğunda negatif bir sayı, 0 veya 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 <=> metoduna sahiptir; bu nedenle bir sınıf genellikle değerlerinden birine karşılaştırma görevini devreder. Diziler öğe öğe karşılaştırılır; böylece aynı anda birkaç alana göre sıralama yapılabilir:

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. Böylece Comparable, kafa karıştırıcı bir NoMethodError hatası vermek yerine < için ArgumentError hatası 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ı tamamla. Weight.parse(text), 500g, 1.2kg veya 2lb (1 lb 453.6 g'dır) değerlerini okur ve gram cinsinden saklar. Comparable modülünü dahil et ve <=> operatörünü gramlara göre tanımla. to_s, gram değerini tam sayıya yuvarlanmış olarak döndürür, örneğin 1200g.

Hazır verilen kod her girdi satırını ayrıştırır, ardından ağırlıkları sıralanmış olarak, en ağırı, en hafifi, ilk ağırlığın 1 kg ile 2 kg arasında olup olmadığını ve en fazla 1 kg ile sınırlandırılmış ilk ağırlığı yazdırır.

Kodunu weight.rb dosyasına yaz. main.rb hazır verilen girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'weight'

# Sağlanan giriş/çıkış 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