Menu
CoddyTech

Slot và quyền 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 23 trên 57.

obj@slot <- value thay đổi một slot. Giống như đối tượng S3, đối tượng S4 là các giá trị: hàm thay đổi một đối tượng sẽ thao tác trên bản sao riêng và trả về bản sao đó:

setClass("Person", slots = c(name = "character", age = "numeric"))
birthday <- function(p) {
  p@age <- p@age + 1
  p
}
ada <- new("Person", name = "Ada", age = 36)
older <- birthday(ada)
cat(ada@age, older@age)

Đầu ra:

36 37

slot(obj, "name") làm tương tự như @ với tên slot dưới dạng chuỗi, nên nó hoạt động với tên được lưu trong một biến. slotNames() liệt kê các slot của một lớp hoặc đối tượng:

setClass("Person", slots = c(name = "character", age = "numeric"))
ada <- new("Person", name = "Ada", age = 36)
for (s in slotNames(ada)) cat(s, "=", format(slot(ada, s)), "\n")
slot(ada, "age") <- 37
print(ada@age)

Đầu ra:

name = Ada 
age = 36 
[1] 37

Mỗi phép gán đều được kiểm tra theo kiểu đã khai báo, không chỉ new(). Giá trị không đúng kiểu sẽ bị từ chối và đối tượng giữ nguyên giá trị cũ:

setClass("Person", slots = c(name = "character", age = "numeric"))
ada <- new("Person", name = "Ada", age = 36)
ada@age <- "old"

Đầu ra:

Error in (function (cl, name, valueClass)  : 
  assignment of an object of class “character” is not valid for @‘age’ in an object of class “Person”; is(value, "numeric") is not TRUE
Execution halted

getSlots() trả về tên của tất cả các slot cùng với kiểu dữ liệu đã khai báo, nhờ đó code có thể chuyển đầu vào dạng văn bản sang kiểu dữ liệu mà slot yêu cầu:

setClass("Person", slots = c(name = "character", age = "numeric"))
types <- getSlots("Person")
print(types)
value <- "40"
if (types[["age"]] == "numeric") value <- as.numeric(value)
print(value + 1)

Đầu ra:

       name         age 
"character"   "numeric" 
[1] 41
challenge icon

Thử thách

Dễ

Lớp Profile trong Profile.R có các slot name và city (ký tự), cùng với age (số). Hoàn thành hai hàm:

  • update_profile(p, field, value) dừng với no field email (dùng call. = FALSE) khi trường không phải là slot; nếu không, hàm chuyển đổi văn bản value bằng as.numeric() khi slot có kiểu số, đặt slot bằng slot() và trả về hồ sơ đã thay đổi.
  • profile_lines(p) trả về một dòng cho mỗi slot, theo thứ tự của các slot: name: Ada.

Code được cung cấp đọc tên, rồi đọc các dòng như city=Paris hoặc age=36, áp dụng từng dòng và in ra các dòng của hồ sơ.

Code của bạn nằm trong Profile.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("Profile.R")

# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
p <- new("Profile", name = input[1], city = "unknown", age = 0)
for (line in input[-1]) {
  kv <- strsplit(line, "=")[[1]]
  p <- tryCatch(update_profile(p, kv[1], kv[2]), error = function(e) {
    cat("error: ", conditionMessage(e), "\n", sep = "")
    p
  })
}
for (l in profile_lines(p)) cat(l, "\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