Menu
CoddyTech

默认方法

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

当没有方法与该类匹配时,UseMethod() 会查找默认方法 name.default。对于泛型函数不认识的每个类,它都是备用方法:

describe <- function(x) UseMethod("describe")
describe.dog <- function(x) paste("a dog called", x$name)
describe.default <- function(x) "something I do not know"
rex <- structure(list(name = "Rex"), class = "dog")
car <- structure(list(), class = "car")
print(describe(rex))
print(describe(car))

输出:

[1] "a dog called Rex"
[1] "something I do not know"

如果没有默认方法,针对未知类调用泛型会报错并停止:

describe <- function(x) UseMethod("describe")
describe.dog <- function(x) paste("a dog called", x$name)
car <- structure(list(), class = "car")
describe(car)

输出:

Error in UseMethod("describe") : 
  no applicable method for 'describe' applied to an object of class "car"
Calls: describe
Execution halted

普通值也会进行分派。没有 class 属性的数字具有隐式类 numeric,文本具有 character,而 TRUE 具有 logical,因此这些名称对应的方法也适用于普通向量:

describe <- function(x) UseMethod("describe")
describe.numeric <- function(x) paste("numbers adding up to", sum(x))
describe.character <- function(x) paste("words:", paste(x, collapse = " "))
describe.default <- function(x) "something else"
print(describe(c(1, 2, 3)))
print(describe(c("a", "b")))
print(describe(TRUE))

输出:

[1] "numbers adding up to 6"
[1] "words: a b"
[1] "something else"

默认方法也可以礼貌地拒绝:使用带有说明信息的 stop(),并在信息中指出类,这样调用方就知道出了什么问题。class(x)[1] 是对象的第一个类:

area <- function(shape) UseMethod("area")
area.square <- function(shape) shape$side^2
area.default <- function(shape) {
  stop("cannot compute the area of a ", class(shape)[1], call. = FALSE)
}
for (s in list(structure(list(side = 2), class = "square"), structure(list(), class = "blob"))) {
  cat(tryCatch(area(s), error = function(e) conditionMessage(e)), "\n")
}

输出:

4 
cannot compute the area of a blob 
challenge icon

挑战

简单

完成 Describe.R 中的泛型 describe(x) 及其处理普通向量的方法:

  • describe.numeric() 返回 3 numbers, sum 6。
  • describe.character() 返回 2 words, longest: apple(如果最长的单词有多个,则返回第一个)。
  • describe.logical() 返回 2 of 3 are TRUE。
  • describe.default() 返回 something else。

提供的代码会读取 num 1,2,3、chr apple,kiwi、lgl TRUE,FALSE,TRUE 这样的行,也会读取包含值的其他任意单词,并将其转换为列表。它会为每一行打印 describe() 的结果。

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

亲手试试

source("Describe.R")

# 提供的输入和输出代码:保持原样
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  values <- strsplit(p[2], ",")[[1]]
  x <- switch(p[1],
    num = as.numeric(values),
    chr = values,
    lgl = as.logical(values),
    list(values))
  cat(describe(x), "\n", sep = "")
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: R 在线编译器