Menu
CoddyTech

定义 S4 类

本课属于 Coddy R 学习旅程的“面向对象编程”单元。第 22 课,共 57 课。

S4 是 R 的正式对象系统。setClass() 用命名的槽及每个槽的类型声明一个类,new() 则创建对象。@ 运算符用于读取槽:

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

输出:

Ada is 36

setClass() 也会返回一个生成器函数。将它赋给一个名称,通常是类名,然后像调用构造函数一样调用它:

Person <- setClass("Person", slots = c(name = "character", age = "numeric"))
bo <- Person(name = "Bo", age = 7)
print(bo@age + 1)
print(is(bo, "Person"))

输出:

[1] 8
[1] TRUE

与 S3 不同,R 会检查各个槽。未知槽或类型错误的值会使 new() 报错并停止,因此 S4 对象始终具有其类声明的结构:

setClass("Person", slots = c(name = "character", age = "numeric"))
p <- new("Person", name = "Cy", age = "ten")

输出:

Error in validObject(.Object) : 
  invalid class “Person” object: invalid object for slot "age" in class "Person": got class "character", should be or extend class "numeric"
Calls: new -> initialize -> initialize -> validObject
Execution halted

未指定的槽会获得其类型的空值,例如 character(0)。prototype 则会设置实际的默认值。旧代码使用 representation() 声明槽,其含义与 slots 相同:

setClass("Task", slots = c(title = "character", done = "logical"),
         prototype = list(done = FALSE))
setClass("Note", representation(text = "character"))
t <- new("Task", title = "Write report")
print(t@done)
print(length(new("Note")@text))

输出:

[1] FALSE
[1] 0
challenge icon

挑战

简单

在 Book.R 中声明 S4 类 Book,包含三个槽:title 和 author 的类型为 character,pages 的类型为 numeric。然后完成 book_label(b),该函数使用 @ 读取槽,并返回 Dune by Frank Herbert (412 pages)。

提供的代码会读取格式为 title;author;pages 的行,为每本书调用 new("Book", ...) 创建对象,输出其标签,最后输出该类的槽名称。

你的代码应写在 Book.R 中。main.R 包含提供的输入/输出代码,不能编辑。

亲手试试

source("Book.R")

# 提供的输入/输出代码:保持原样
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, ";")[[1]]
  b <- new("Book", title = p[1], author = p[2], pages = as.numeric(p[3]))
  cat(book_label(b), "\n", sep = "")
}
cat("slots: ", paste(slotNames("Book"), collapse = ", "), "\n", sep = "")
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: R 在线编译器