case và lớp
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 35 trên 57.
case có thể phân nhánh dựa trên lớp của một giá trị. when Integer khớp với mọi số nguyên, vì case so sánh bằng ===, còn Integer === 5 kiểm tra xem 5 có phải là một Integer hay không (is_a?):
def describe(value)
case value
when Integer then "integer #{value}"
when Float then format("float %.2f", value)
when String then "text of #{value.size} chars"
when nil then "nothing"
else "other: #{value.class}"
end
end
[5, 2.5, "hi", nil, [1, 2]].each { |v| puts describe(v) }Đầu ra:
integer 5
float 2.50
text of 2 chars
nothing
other: ArrayVì === trên một lớp hoạt động theo is_a?, nên when có lớp cha cũng khớp với các lớp con của nó. Sắp xếp các nhánh từ lớp cụ thể nhất đến lớp tổng quát nhất:
class Animal
end
class Dog < Animal
end
def kind(x)
case x
when Dog then "a dog"
when Animal then "some animal"
else "not an animal"
end
end
puts kind(Dog.new)
puts kind(Animal.new)
puts kind("Rex")
puts Animal === Dog.newĐầu ra:
a dog
some animal
not an animal
trueMột when có thể liệt kê nhiều lớp, và các nhánh có thể xử lý giá trị thực sự, chẳng hạn như tính tổng một cấu trúc lồng nhau gồm nhiều kiểu dữ liệu:
def total(value)
case value
when Integer, Float then value
when String then value.to_f
when Array then value.sum { |v| total(v) }
when Hash then total(value.values)
else 0
end
end
puts total([1, "2.5", { a: 3, b: [4, nil] }])Đầu ra:
10.5Rẽ nhánh theo lớp phù hợp với các giá trị mà bạn không thể thêm phương thức mới vào lớp của chúng, chẳng hạn như số, chuỗi và mảng, hoặc dữ liệu từ bên ngoài. Với các lớp của riêng mình, hãy ưu tiên tính đa hình: khi có lớp mới, bạn chỉ cần thêm một phương thức, thay vì thêm nhánh mới vào mọi case:
# Các lớp (class) do bạn tự tạo: để mỗi lớp tự trả lời
shape.area
# Các giá trị (value) có sẵn từ bên ngoài: rẽ nhánh theo lớp
case value
when Integer then ...
when String then ...
endThử thách
DễHoàn thiện hàm trợ giúp describe(value) trong functions.rb bằng một case dựa trên lớp của giá trị. Hàm trả về integer 5 (odd) hoặc integer 4 (even), float 2.50 với hai chữ số thập phân, text "hi" (2 chars), list of 3: 1, a, 2.5 (các phần tử được nối bằng to_s), nothing cho nil và other Symbol cho mọi giá trị khác. Trong các bài kiểm tra, symbol là kiểu duy nhất khác.
Code được cung cấp chuyển từng dòng đầu vào thành một giá trị (số nguyên, số thập phân, danh sách [a,b], nil, symbol :name hoặc văn bản), rồi in kết quả của describe cho từng giá trị.
Code của bạn nằm trong functions.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 'functions'
# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input = []
while (line = gets)
input << line.chomp
end
def parse(text)
return Integer(text) if text.match?(/\A-?\d+\z/)
return Float(text) if text.match?(/\A-?\d+\.\d+\z/)
return nil if text == "nil"
return text[1..].to_sym if text.start_with?(":")
return text[1...-1].split(",").map { |t| parse(t) } if text.start_with?("[")
text
end
input.each { |line| puts describe(parse(line)) }
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ệTự luyện tập: Trình biên dịch Ruby online