El módulo Comparable
Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 29 de 57.
El módulo integrado de Ruby Comparable proporciona a una clase los operadores <, <=, ==, >, >= y los métodos between? y clamp. Necesita un método de la clase: <=>, que devuelve un número negativo, 0 o un número positivo cuando el objeto es menor, igual o mayor:
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))Salida:
true
true
trueLos números y las cadenas ya tienen <=>, por lo que una clase normalmente delega en uno de sus valores. Comparar arrays funciona elemento por elemento, lo que permite ordenar por varios campos a la vez:
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 > cSalida:
true
truesort, min y max también usan <=>, por lo que los objetos de la clase se pueden ordenar sin un bloque. clamp mantiene un valor entre otros dos:
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))Salida:
150g, 400g, 900g
900g
1000g<=> debería devolver nil cuando el otro objeto no se pueda comparar. Comparable después genera ArgumentError para < y devuelve false para ==, en lugar de fallar con un confuso NoMethodError:
def <=>(other)
return nil unless other.is_a?(Weight)
grams <=> other.grams
end
Weight.new(1) == 5 # false
Weight.new(1) < 5 # ArgumentError: comparación de Weight con 5 fallóDesafío
FácilCompleta la clase Weight. Weight.parse(text) lee 500g, 1.2kg o 2lb (1 lb son 453.6 g) y almacena los gramos. Incluye Comparable y define <=> sobre los gramos. to_s devuelve los gramos redondeados a un número entero, como 1200g.
El código proporcionado analiza cada línea de entrada y después imprime los pesos ordenados, el más pesado, el más ligero, si el primer peso está entre 1 kg y 2 kg y el primer peso limitado a como máximo 1 kg.
Tu código va en weight.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
require_relative 'weight'
# Código de entrada/salida suministrado: déjalo tal como está
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"))}"
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Clases y objetos
Trabajar con archivosDefinir clasesVariables de instanciaMétodos y selfto_s e inspectRepaso: tarjeta de biblioteca4Encapsulación
Métodos privadosMétodos protegidosAsignadores privadosProtección del estadoRepaso: máquina expendedora7Polimorfismo y tipado pato
PolimorfismoTipado patoMétodos abstractoscase y clasesRepaso: métodos de pago2Accesores y self
Lectores y escritoresSetters personalizadosself en los métodosIdentidad e igualdadRepaso: lista de contactos5Herencia
SubclasesSobrescritura de métodosLlamar a superis_a? y ancestrosRepaso - Nómina del personal8Métodos especiales
Igualdad y hashMétodos de operadoresIndexación y adiciónColecciones personalizadasRepaso: fracciones11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de libros3Métodos y variables de clase
Métodos de claseVariables de instancia de claseConstantesMétodos de fábricaRepaso: códigos de cupón6Módulos y mixins
Módulos e inclusiónExtender objetosEl módulo ComparableEl módulo EnumerableRepaso: liga deportivaPractica por tu cuenta: Compilador de Ruby online