Menu
CoddyTech

Truy cập theo chỉ số và thêm phần tử

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 39 trên 57.

obj[key] gọi phương thức [], còn obj[key] = value gọi []=. Định nghĩa các phương thức này giúp lớp có cú pháp dấu ngoặc vuông như mảng và hash, với ý nghĩa tùy theo cách bạn muốn:

class Inventory
  def initialize
    @stock = Hash.new(0)
  end

  def [](name)
    @stock[name]
  end

  def []=(name, qty)
    @stock[name] = qty
  end
end

inv = Inventory.new
inv["apple"] = 5
inv["apple"] += 2
puts inv["apple"]
puts inv["pear"]

Đầu ra:

7
0

[] có thể nhận nhiều đối số, chẳng hạn như hàng và cột, rồi kiểm tra chúng. IndexError là lỗi thường gặp khi vị trí không tồn tại:

class Board
  def initialize(size)
    @size = size
    @cells = Array.new(size) { Array.new(size, ".") }
  end

  def [](row, col)
    check(row, col)
    @cells[row][col]
  end

  def []=(row, col, mark)
    check(row, col)
    @cells[row][col] = mark
  end

  def check(row, col)
    raise IndexError, "no cell #{row},#{col}" unless row.between?(0, @size - 1) && col.between?(0, @size - 1)
  end
end

b = Board.new(3)
b[1, 1] = "X"
puts b[1, 1] + b[0, 0]
begin
  b[3, 0]
rescue IndexError => e
  puts e.message
end

Đầu ra:

X.
no cell 3,0

<< là toán tử nối thêm. Trả về self từ toán tử này cho phép bạn nối chuỗi lệnh, như list << a << b trên mảng:

class Shelf
  def initialize
    @books = []
  end

  def <<(title)
    @books << title
    self
  end

  def to_s
    @books.join(" | ")
  end
end

shelf = Shelf.new
shelf << "Dune" << "Emma" << "Ulysses"
puts shelf

Đầu ra:

Dune | Emma | Ulysses

Phép gán thông qua []= trả về giá trị được gán, chứ không phải giá trị mà phương thức trả về, giống như mọi phương thức setter. Dấu ngoặc vuông và << tạo cho một lớp một giao diện nhỏ, quen thuộc:

inv["apple"] = 5          # gọi []=("apple", 5), biểu thức (expression) có giá trị là 5
inv["apple"]              # gọi []("apple")
shelf << "Dune" << "Emma"  # << trả về self nên có thể gọi liên tiếp
board[1, 2] = "X"         # []=(1, 2, "X")
challenge icon

Thử thách

Dễ

Hoàn thiện lớp Inventory. inv[name] trả về số lượng của một món hàng (0 nếu chưa biết), inv[name] = qty đặt số lượng đó, còn inv << name thêm một món hàng đó và trả về kho hàng để có thể nối chuỗi các lệnh gọi. to_s trả về apple: 3, pear: 1 theo thứ tự bảng chữ cái của tên, bỏ qua các món hàng có số lượng 0, hoặc trả về empty.

Code được cung cấp đọc các lệnh: set apple 5, add apple pear pear (lệnh này nối chuỗi << cho từng tên), get apple và print, rồi in kết quả của get và print.

Code của bạn nằm trong inventory.rb. main.rb chứa code đầu vào/đầu ra được cung cấp và không thể chỉnh sửa.

Tự làm thử

require_relative 'inventory'

# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input = []
while (line = gets)
  input << line.chomp
end
inv = Inventory.new
input.each do |line|
  cmd, *args = line.split
  case cmd
  when "set" then inv[args[0]] = args[1].to_i
  when "add" then args.reduce(inv) { |target, name| target << name }
  when "get" then puts inv[args[0]]
  else puts inv
  end
end
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