S3 và S4 có vẻ là phương pháp chính thức (tức là được xây dựng) cho lập trình OO. Tôi đã bắt đầu sử dụng một sự kết hợp của S3 với các hàm được nhúng trong hàm/phương thức của hàm dựng. Mục tiêu của tôi là có một cú pháp kiểu $ method() đối tượng để tôi có các trường bán riêng. Tôi nói bán tư nhân bởi vì không có cách nào thực sự che giấu chúng (theo như tôi biết). Dưới đây là một ví dụ đơn giản mà không thực sự làm bất cứ điều gì:
#' Constructor
EmailClass <- function(name, email) {
nc = list(
name = name,
email = email,
get = function(x) nc[[x]],
set = function(x, value) nc[[x]] <<- value,
props = list(),
history = list(),
getHistory = function() return(nc$history),
getNumMessagesSent = function() return(length(nc$history))
)
#Add a few more methods
nc$sendMail = function(to) {
cat(paste("Sending mail to", to, 'from', nc$email))
h <- nc$history
h[[(length(h)+1)]] <- list(to=to, timestamp=Sys.time())
assign('history', h, envir=nc)
}
nc$addProp = function(name, value) {
p <- nc$props
p[[name]] <- value
assign('props', p, envir=nc)
}
nc <- list2env(nc)
class(nc) <- "EmailClass"
return(nc)
}
#' Define S3 generic method for the print function.
print.EmailClass <- function(x) {
if(class(x) != "EmailClass") stop();
cat(paste(x$get("name"), "'s email address is ", x$get("email"), sep=''))
}
Và một số mã kiểm tra:
test <- EmailClass(name="Jason", "[email protected]")
test$addProp('hello', 'world')
test$props
test
class(test)
str(test)
test$get("name")
test$get("email")
test$set("name", "Heather")
test$get("name")
test
test$sendMail("[email protected]")
test$getHistory()
test$sendMail("[email protected]")
test$getNumMessagesSent()
test2 <- EmailClass("Nobody", "[email protected]")
test2
test2$props
test2$getHistory()
test2$sendMail('[email protected]')
đây là một liên kết đến một bài viết trên blog, tôi đã viết về phương pháp này: http://bryer.org/2012/object-oriented-programming-in-r tôi sẽ chào đón nhận xét, phê bình và gợi ý cho phương pháp này vì tôi không thuyết phục bản thân mình nếu đây là cách tiếp cận tốt nhất. Tuy nhiên, đối với vấn đề tôi đã cố gắng để giải quyết nó đã làm việc tuyệt vời. Cụ thể, đối với gói makeR (http://jbryer.github.com/makeR), tôi không muốn người dùng thay đổi trường dữ liệu trực tiếp vì tôi cần đảm bảo rằng tệp XML đại diện cho trạng thái của đối tượng của tôi sẽ được đồng bộ hóa. Điều này làm việc hoàn hảo miễn là người dùng tuân thủ các quy tắc tôi phác thảo trong tài liệu.
Thông tin về lớp tham chiếu: http://stackoverflow.com/questions/5137199/what-is-the-significance-of-the-new-reference-classes –
Cảm ơn, bạn có thể đăng lại liên kết dưới dạng câu trả lời không? Sẽ rất tuyệt nếu bạn có thể bao gồm một bản tóm tắt nhỏ về các lớp Tham chiếu là gì và tại sao chúng lại thích hợp hơn với các lớp S3/S4. –
Một con chim nhỏ thì thầm vào tai tôi rằng một cuốn sách về điều này sẽ được sắp tới bởi John Chambers. Nhưng đừng nói với bất cứ ai tôi đã nói rằng ... ;-) –