Menu
CoddyTech

Môi trường dưới dạng đối tượng

Thuộc phần Lập trình hướng đối tượng trong hành trình R của Coddy. Bài học 18 trên 57.

Môi trường là một tập hợp các giá trị có tên, giống như danh sách, được tạo bằng new.env(). Điểm khác biệt là môi trường không bao giờ được sao chép: mọi biến tham chiếu đến nó đều thấy cùng một đối tượng, vì vậy thay đổi qua một tên sẽ hiển thị qua tất cả các tên đó:

e <- new.env()
e$count <- 1
alias <- e
alias$count <- 99
print(e$count)
l <- list(count = 1)
copy <- l
copy$count <- 99
print(l$count)

Đầu ra:

[1] 99
[1] 1

Một hàm nhận một môi trường sẽ thay đổi đối tượng của bên gọi. Hàm không cần trả về gì, và bên gọi không gán kết quả:

deposit <- function(acc, x) acc$balance <- acc$balance + x
acc <- new.env()
acc$balance <- 10
deposit(acc, 5)
deposit(acc, 5)
print(acc$balance)

Đầu ra:

[1] 20

assign(), get() và exists() làm việc với tên được lưu trong một biến, còn ls() liệt kê tên trong môi trường theo thứ tự đã sắp xếp:

e <- new.env()
for (fruit in c("pear", "apple")) assign(fruit, nchar(fruit), envir = e)
print(ls(e))
print(get("pear", envir = e))
print(exists("kiwi", envir = e))

Đầu ra:

[1] "apple" "pear" 
[1] 4
[1] FALSE

Môi trường có thuộc tính lớp là một đối tượng S3 có ngữ nghĩa tham chiếu: các phương thức của nó hoạt động như thường lệ, còn các hàm thay đổi nó sẽ thay đổi trực tiếp tại chỗ:

new_wallet <- function(coins = 0) {
  w <- new.env()
  w$coins <- coins
  class(w) <- "wallet"
  w
}
print.wallet <- function(x, ...) {
  cat("wallet with", x$coins, "coins\n")
  invisible(x)
}
spend <- function(w, n) w$coins <- w$coins - n
w <- new_wallet(10)
spend(w, 3)
w

Đầu ra:

wallet with 7 coins
challenge icon

Thử thách

Dễ

Kho hàng là một môi trường thuộc lớp inventory, có một biến items, là một vector số có tên lưu số lượng hàng. Hoàn thành Inventory.R:

  • new_inventory() tạo môi trường với items trống (c() là được) và lớp.
  • add_stock(inv, item, n) thêm n vào số lượng hàng của mặt hàng, bắt đầu từ 0 nếu là mặt hàng mới.
  • take_stock(inv, item, n) lấy đi n và trả về TRUE khi có đủ hàng, nếu không thì không thay đổi gì và trả về FALSE.
  • stock_of(inv, item) trả về số lượng hàng, bằng 0 nếu không biết mặt hàng đó.

Các hàm thay đổi kho hàng tại chỗ và không trả về kho. Đoạn code được cung cấp đọc các lệnh add apple 5 và take apple 2, in kết quả của từng lệnh take, rồi in mọi mặt hàng theo thứ tự bảng chữ cái.

Đặt code của bạn trong Inventory.R. main.R 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ử

source("Inventory.R")

# Đoạn code đầu vào/đầu ra đã cho: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
inv <- new_inventory()
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  n <- as.numeric(p[3])
  if (p[1] == "add") add_stock(inv, p[2], n)
  if (p[1] == "take") cat("take ", p[2], ": ", if (take_stock(inv, p[2], n)) "ok" else "not enough", "\n", sep = "")
}
for (item in sort(names(inv$items))) cat(item, ": ", stock_of(inv, item), "\n", sep = "")
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 R online