Menu
CoddyTech

Hàm truy cậ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 19 trên 57.

Tính đóng gói có nghĩa là code khác làm việc với một đối tượng thông qua các hàm thay vì truy cập trực tiếp vào các trường của đối tượng. Hàm getter đọc một giá trị, còn hàm setter thay đổi giá trị đó. Với danh sách S3, hàm setter trả về bản sao đã thay đổi:

new_member <- function(name) structure(list(name = name), class = "member")
get_name <- function(p) p$name
set_name <- function(p, value) {
  p$name <- value
  p
}
p <- new_member("ada")
p <- set_name(p, "Ada Lovelace")
print(get_name(p))

Đầu ra:

[1] "Ada Lovelace"

Các phương thức truy cập cho phép đối tượng thay đổi cách lưu trữ dữ liệu mà không làm hỏng code sử dụng nó. Nhiệt kế này lưu nhiệt độ theo độ C, còn hàm getter tính độ F khi được yêu cầu, nên bên gọi không bao giờ thấy trực tiếp trường dữ liệu:

new_thermo <- function(c) structure(list(c = c), class = "thermo")
celsius <- function(t) t$c
fahrenheit <- function(t) t$c * 9 / 5 + 32
t <- new_thermo(25)
cat(celsius(t), fahrenheit(t))

Đầu ra:

25 77

Các setter riêng của R, chẳng hạn như names(x) <- ..., là hàm thay thế. Một hàm có tên "name<-" với các tham số x và value cho phép bên gọi viết name(p) <- "Bo"; R gọi hàm đó rồi gán kết quả trở lại cho p:

new_member <- function(name) structure(list(name = name), class = "member")
name <- function(p) p$name
"name<-" <- function(x, value) {
  x$name <- trimws(value)
  x
}
p <- new_member("ada")
name(p) <- "  Bo  "
print(name(p))

Đầu ra:

[1] "Bo"

Hàm getter của một đối tượng closure trả về bản sao của dữ liệu riêng tư. Thay đổi bản sao đó không làm thay đổi đối tượng, vì vậy cách duy nhất để truy cập là thông qua các hàm của chính đối tượng:

make_list <- function() {
  items <- character(0)
  list(add = function(x) items <<- c(items, x),
       get_items = function() items)
}
todo <- make_list()
todo$add("milk")
mine <- todo$get_items()
mine[1] <- "HACKED"
print(todo$get_items())

Đầu ra:

[1] "milk"
challenge icon

Thử thách

Dễ

Một contact là một danh sách S3 thuộc lớp contact, có các trường name và email. Hoàn thiện Contact.R:

  • new_contact(name, email) lưu email sau khi loại bỏ khoảng trắng ở đầu và cuối, đồng thời chuyển thành chữ thường.
  • Các hàm getter contact_name(x) và contact_email(x).
  • Hàm thay thế "contact_email<-", lưu email mới sau khi loại bỏ khoảng trắng ở đầu và cuối, đồng thời chuyển thành chữ thường, để bên gọi có thể viết contact_email(c1) <- value.

Code được cung cấp đọc name,email, sau đó đọc các email mới, rồi in Ada <ada@x.com> sau mỗi lần thay đổi và in tên các trường đã lưu ở cuối.

Viết code của bạn trong Contact.R. main.R chứa code đầu vào/đầu ra được cung cấp và không thể chỉnh sửa.

Tự làm thử

source("Contact.R")

# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
p <- strsplit(input[1], ",")[[1]]
c1 <- new_contact(p[1], p[2])
cat(contact_name(c1), " <", contact_email(c1), ">\n", sep = "")
for (value in input[-1]) {
  contact_email(c1) <- value
  cat(contact_name(c1), " <", contact_email(c1), ">\n", sep = "")
}
cat("stored fields: ", paste(names(unclass(c1)), collapse = ", "), "\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