Menu
CoddyTech

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: Array

Vì === 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
true

Mộ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.5

Rẽ 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 ...
end
challenge icon

Thử 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)) }
quiz iconTự kiểm tra

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

Tự luyện tập: Trình biên dịch Ruby online