Ngữ nghĩa sao chép
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 39 trên 57.
Đối tượng S3 và S4 là các giá trị: hàm thay đổi một đối tượng chỉ thay đổi bản sao của chính nó. Đối tượng RC là các tham chiếu: đối tượng của bên gọi sẽ thay đổi. Cùng một hàm hoạt động khác nhau với hai loại này:
setClass("S4Box", slots = c(n = "numeric"))
RCBox <- setRefClass("RCBox", fields = list(n = "numeric"))
bump_s4 <- function(b) { b@n <- b@n + 1; invisible(b) }
bump_rc <- function(b) b$n <- b$n + 1
v <- new("S4Box", n = 1)
r <- RCBox$new(n = 1)
bump_s4(v)
bump_rc(r)
cat(v@n, r$n)Đầu ra:
1 2$copy() tạo một đối tượng mới, độc lập với các giá trị trường giống hệt. Thay đổi bản sao không làm thay đổi đối tượng gốc:
Account <- setRefClass("Account", fields = list(balance = "numeric"))
a <- Account$new(balance = 100)
alias <- a
backup <- a$copy()
alias$balance <- 0
cat(a$balance, backup$balance)Đầu ra:
0 100Một danh sách có thể chứa cùng một đối tượng RC nhiều lần. Khi thay đổi một phần tử, tất cả phần tử đều thay đổi. Hãy tạo một đối tượng mới cho mỗi phần tử nếu chúng cần độc lập:
Counter <- setRefClass("Counter", fields = list(n = "numeric"))
one <- Counter$new(n = 0)
same <- list(one, one, one)
same[[1]]$n <- 5
fresh <- lapply(1:3, function(i) Counter$new(n = 0))
fresh[[1]]$n <- 5
cat(same[[3]]$n, fresh[[3]]$n)Đầu ra:
5 0identical(a, b) trả về TRUE với hai tên của cùng một đối tượng RC, còn với một bản sao thì trả về FALSE, ngay cả khi các trường vẫn bằng nhau:
Account <- setRefClass("Account", fields = list(balance = "numeric"))
a <- Account$new(balance = 100)
b <- a
c2 <- a$copy()
cat(identical(a, b), identical(a, c2), c2$balance == a$balance)Đầu ra:
TRUE FALSE TRUEThử thách
DễTrình soạn thảo văn bản lưu các điểm lưu. Khai báo lớp tham chiếu (Reference Class) Document trong Document.R với thuộc tính text (kiểu chuỗi) và phương thức (method) type(s) nối s vào văn bản. Sau đó, viết checkpoint(doc), hàm này trả về một bản sao độc lập của tài liệu.
Định nghĩa có các phương thức được bọc trong suppressMessages(). Code được cung cấp bắt đầu bằng một điểm lưu, sau đó đọc các lệnh: save lưu checkpoint(doc), undo quay lại bản sao của điểm lưu gần nhất, còn mọi dòng khác sẽ được nhập vào tài liệu. Sau mỗi lệnh, code in ra văn bản và văn bản đã lưu, vì vậy điểm lưu không bao giờ được thay đổi khi bạn tiếp tục nhập.
Đặt code của bạn trong Document.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("Document.R")
# Đoạn code đầu vào/đầu ra đã cung cấp: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
doc <- Document$new(text = "")
saved <- checkpoint(doc)
for (cmd in input) {
if (cmd == "save") {
saved <- checkpoint(doc)
} else if (cmd == "undo") {
doc <- checkpoint(saved)
} else {
doc$type(cmd)
}
cat(cmd, " -> [", doc$text, "] saved [", saved$text, "]\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ẩm8Lớp tham chiếu
Định nghĩa lớp tham chiếuPhương thức và cập nhật trườngNgữ nghĩa sao chépKế thừa và callSuperÔn tập: hàng đợi tác vụTự luyện tập: Trình biên dịch R online