Menu
CoddyTech

Mở rộng bằng contains

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 32 trên 57.

contains = "Animal" tạo một lớp con S4 mới của Animal. Lớp con có tất cả các slot của lớp cha cùng với các slot riêng, và new() nhận tất cả các slot đó:

setClass("Animal", slots = c(name = "character", age = "numeric"))
setClass("Dog", contains = "Animal", slots = c(breed = "character"))
rex <- new("Dog", name = "Rex", age = 3, breed = "collie")
print(slotNames("Dog"))
cat(rex@name, rex@breed)

Đầu ra:

[1] "breed" "name"  "age"  
Rex collie

Các phương thức được viết cho lớp cha cũng hoạt động với lớp con. Khi một generic không có phương thức cho Dog, S4 dùng phương thức cho Animal:

setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
invisible(setGeneric("intro", function(a) standardGeneric("intro")))
setMethod("intro", "Animal", function(a) paste("I am", a@name))
print(intro(new("Dog", name = "Rex")))

Đầu ra:

[1] "I am Rex"

Lớp con ghi đè phương thức của lớp cha bằng cách định nghĩa phương thức riêng cho cùng một kiểu tổng quát. Lớp cụ thể nhất sẽ được ưu tiên, còn các lớp con khác vẫn dùng phương thức của lớp cha:

setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Cat", contains = "Animal")
invisible(setGeneric("sound", function(a) standardGeneric("sound")))
setMethod("sound", "Animal", function(a) "...")
setMethod("sound", "Dog", function(a) "woof")
cat(sound(new("Dog", name = "Rex")), sound(new("Cat", name = "Tom")))

Đầu ra:

woof ...

is(x, "Animal") trả về TRUE với một con chó, và một slot được khai báo là "Animal" chấp nhận một Dog. Code viết cho lớp cha hoạt động với mọi lớp con:

setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Owner", slots = c(pet = "Animal"))
rex <- new("Dog", name = "Rex")
o <- new("Owner", pet = rex)
cat(is(rex, "Animal"), is(o@pet, "Dog"))

Đầu ra:

TRUE TRUE
challenge icon

Thử thách

Dễ

Nhân viên và quản lý là các lớp S4 trong hai tệp. Employee.R khai báo Employee (các thuộc tính name, salary) và hàm tổng quát describe(), đồng thời cần có một phương thức cho Employee trả về Bo earns 40000. Trong Manager.R, hãy khai báo Manager, lớp này chứa Employee và thêm thuộc tính reports (kiểu số), đồng thời ghi đè describe() để hàm trả về Ada earns 60000 and manages 4.

Code được cung cấp đọc các dòng employee Bo 40000 hoặc manager Ada 60000 4 và in ra describe(), thông tin đối tượng có phải là nhân viên hay không và các thuộc tính của đối tượng.

Code của bạn đặt trong Employee.R và Manager.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("Employee.R")
source("Manager.R")

# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  x <- if (p[1] == "manager") {
    new("Manager", name = p[2], salary = as.numeric(p[3]), reports = as.numeric(p[4]))
  } else {
    new("Employee", name = p[2], salary = as.numeric(p[3]))
  }
  cat(describe(x), "\n", sep = "")
  cat("is an employee: ", is(x, "Employee"), ", slots: ", paste(slotNames(x), 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