Module Comparable
Thuộc phần Lập trình hướng đối tượng trong hành trình Ruby của Coddy. Bài học 29 trên 57.
Mô-đun tích hợp sẵn Comparable của Ruby cung cấp cho một lớp các toán tử <, <=, ==, >, >= và các phương thức between? và clamp. Mô-đun cần lớp định nghĩa một phương thức: <=>, phương thức này trả về một số âm, 0 hoặc một số dương khi đối tượng nhỏ hơn, bằng hoặc lớn hơn:
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))Đầu ra:
true
true
trueSố và chuỗi đã có <=>, nên một lớp thường ủy quyền việc so sánh cho một trong các giá trị của nó. Khi so sánh mảng, chương trình xét từng phần tử, nhờ đó có thể sắp xếp theo nhiều trường cùng lúc:
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Đầu ra:
true
truesort, min và max cũng dùng <=>, nên bạn có thể sắp xếp các đối tượng của lớp mà không cần khối lệnh. clamp giữ một giá trị trong khoảng giữa hai giá trị khác:
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))Đầu ra:
150g, 400g, 900g
900g
1000g<=> nên trả về nil khi không thể so sánh với đối tượng còn lại. Khi đó, Comparable sẽ phát sinh ArgumentError với < và trả về false với ==, thay vì gặp lỗi NoMethodError khó hiểu:
def <=>(other)
return nil unless other.is_a?(Weight)
grams <=> other.grams
end
Weight.new(1) == 5 # false
Weight.new(1) < 5 # ArgumentError: không thể so sánh Weight với 5Thử thách
DễHoàn thiện lớp Weight. Weight.parse(text) đọc 500g, 1.2kg hoặc 2lb (1 lb bằng 453.6 g) và lưu số gam. Thêm Comparable và định nghĩa <=> dựa trên số gam. to_s trả về số gam được làm tròn thành số nguyên, như 1200g.
Code được cung cấp phân tích từng dòng đầu vào, sau đó in các khối lượng theo thứ tự đã sắp xếp, khối lượng nặng nhất, nhẹ nhất, liệu khối lượng đầu tiên có nằm trong khoảng từ 1 kg đến 2 kg hay không, và khối lượng đầu tiên sau khi giới hạn ở mức tối đa 1 kg.
Đặt code của bạn trong weight.rb. main.rb chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.
Tự làm thử
require_relative 'weight'
# Đoạn code đầu vào/đầu ra đã cho: giữ nguyê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"))}"
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Lớp và đối tượng
Làm việc với tệpĐịnh nghĩa lớpBiến instancePhương thức và selfto_s và inspectÔn tập: thẻ thư viện4Tính đóng gói
Phương thức riêng tưPhương thức được bảo vệPhương thức thiết lập riêng tưBảo vệ trạng tháiÔn tập: máy bán hàng tự động7Tính đa hình và duck typing
Tính đa hìnhDuck typingPhương thức trừu tượngcase và lớpÔn tập: phương thức thanh toán2Phương thức truy cập và self
Phương thức đọc và ghiPhương thức gán tùy chỉnhself trong phương thứcĐịnh danh và tính bằng nhauÔn tập: Danh sách liên hệ3Phương thức và biến của lớp
Phương thức lớpBiến thực thể của lớpHằng sốPhương thức tạo đối tượngÔn tập: mã giảm giá6Module và mixin
Module và includeMở rộng đối tượngModule ComparableModule EnumerableÔn tập: giải đấu thể thaoTự luyện tập: Trình biên dịch Ruby online