Bảo vệ trạng thái
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 20 trên 57.
Phương thức setter là nơi duy nhất giá trị có thể thay đổi, vì vậy đây là nơi thực thi các quy tắc. Phương thức này kiểm tra trước và gọi stop() trước khi có bất kỳ thay đổi nào, nhờ đó đối tượng luôn hợp lệ:
make_account <- function(balance = 0) {
withdraw <- function(x) {
if (x <= 0) stop("amount must be positive", call. = FALSE)
if (x > balance) stop("insufficient funds", call. = FALSE)
balance <<- balance - x
}
list(withdraw = withdraw, balance = function() balance)
}
acc <- make_account(50)
msg <- tryCatch(acc$withdraw(80), error = function(e) conditionMessage(e))
cat(msg, "/", acc$balance())Đầu ra:
insufficient funds / 50lockBinding("rate", e) khiến một biến trong môi trường trở thành chỉ đọc. Gán giá trị cho biến đó sau này sẽ gây ra lỗi, còn các biến khác vẫn có thể ghi được:
loan <- new.env()
loan$rate <- 0.05
loan$owed <- 1000
lockBinding("rate", loan)
loan$owed <- 900
msg <- tryCatch({ loan$rate <- 0; "changed" }, error = function(e) conditionMessage(e))
cat(msg, "\n")
cat(loan$rate, loan$owed, "\n")Đầu ra:
cannot change value of locked binding for 'rate'
0.05 900 lockEnvironment(e) ngăn thêm biến mới. Với bindings = TRUE, hàm này cũng khóa mọi biến hiện có, khiến toàn bộ đối tượng chỉ có thể đọc:
cfg <- new.env()
cfg$theme <- "dark"
lockEnvironment(cfg, bindings = TRUE)
for (step in c("change", "add")) {
msg <- tryCatch({
if (step == "change") cfg$theme <- "light" else cfg$size <- 12
"done"
}, error = function(e) conditionMessage(e))
cat(step, ":", msg, "\n")
}Đầu ra:
change : cannot change value of locked binding for 'theme'
add : cannot add bindings to a locked environment local() chạy code trong một môi trường mới và trả về giá trị cuối cùng. Các hàm trợ giúp được định nghĩa bên trong sẽ không hiển thị ra bên ngoài. Nhờ vậy, một tệp có thể giữ riêng tư một hàm, dù source() đưa mọi thứ khác vào môi trường toàn cục:
circle_area <- local({
square <- function(x) x * x
function(r) pi * square(r)
})
print(round(circle_area(2), 2))
print(exists("square"))Đầu ra:
[1] 12.57
[1] FALSEThử thách
DễHoàn thiện hàm tạo make_account(owner) trong Account.R. Số dư bắt đầu từ 0 và lịch sử riêng ghi lại mọi thay đổi dưới dạng +50 hoặc -20. Danh sách được trả về có bốn hàm:
deposit(x)dừng với lỗiamount must be positivenếuxkhông lớn hơn 0;withdraw(x)dừng với lỗiamount must be positivehoặcinsufficient funds;balance()trả về số dư;history()trả về lịch sử dưới dạng một vector ký tự.
Kiểm tra trước khi thay đổi bất cứ điều gì và dùng call. = FALSE. Code được cung cấp đọc tên chủ tài khoản, sau đó đọc các dòng dep 50 hoặc wd 20, in ra ok hoặc error: cùng thông báo tương ứng cho mỗi dòng, thử thay đổi một bản sao của lịch sử, rồi in số dư và lịch sử.
Hãy viết code trong Account.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("Account.R")
# Đoạn code đầu vào/đầu ra đã cho: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
acc <- make_account(input[1])
for (line in input[-1]) {
p <- strsplit(line, " ")[[1]]
amount <- as.numeric(p[2])
msg <- tryCatch({
if (p[1] == "dep") acc$deposit(amount) else acc$withdraw(amount)
"ok"
}, error = function(e) paste("error:", conditionMessage(e)))
cat(line, ": ", msg, "\n", sep = "")
}
h <- acc$history()
h[1] <- "tampered"
cat("balance: ", acc$balance(), "\n", sep = "")
cat("history: ", paste(acc$history(), collapse = ", "), "\n", sep = "")
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
1Kiến thức cơ bản về S3
Làm việc với tệpDanh sách với một lớpHàm khởi tạoPhương thức in ra và định dạngTrình xác thực và hàm hỗ trợÔn tập: nhiệt độ4Tính đóng gói trong R
Closure dưới dạng đối tượngMôi trường dưới dạng đối tượngHàm truy cậpBảo vệ trạng tháiÔn tập: đồng hồ tính phí đỗ xe2S3, hàm generic và phương thức
Hàm generic và UseMethodPhương thức mặc địnhPhương thức cho hàm generic cơ sởCơ bản về NextMethodÔn tập: diện tích hình5Các lớp S4
Định nghĩa lớp S4Slot và quyền truy cậpKiểm tra tính hợp lệPhương thức showÔn tập: Danh mục sản phẩmTự luyện tập: Trình biên dịch R online