打印与格式化方法
本课属于 Coddy R 学习旅程的“面向对象编程”单元。第 4 课,共 57 课。
打印一个值时,R 会调用函数 print()。如果没有为类设置特殊处理,S3 对象会像列表一样打印,后面跟着类属性,这样很难阅读:
m <- structure(list(amount = 9.5, currency = "EUR"), class = "money")
print(m)输出:
$amount
[1] 9.5
$currency
[1] "EUR"
attr(,"class")
[1] "money"方法是一个名为 generic.class 的函数。当 print() 接收到一个 money 类的对象时,它会查找 print.money() 并调用它。打印方法使用 cat() 输出,并以 invisible(x) 结束,因此它会返回对象,而不会再次打印对象:
print.money <- function(x, ...) {
cat("<money ", x$amount, " ", x$currency, ">\n", sep = "")
invisible(x)
}
m <- structure(list(amount = 9.5, currency = "EUR"), class = "money")
print(m)
m输出:
<money 9.5 EUR>
<money 9.5 EUR>format() 是将值转换为文本的通用函数。format.money() 方法会返回文本,而不是打印文本,这样其他代码就可以将它放进句子中,打印方法也可以重用它:
format.money <- function(x, ...) {
sprintf("%.2f %s", x$amount, x$currency)
}
print.money <- function(x, ...) {
cat("Money:", format(x), "\n")
invisible(x)
}
m <- structure(list(amount = 9.5, currency = "EUR"), class = "money")
m
cat("You owe", format(m), "\n")输出:
Money: 9.50 EUR
You owe 9.50 EUR 方法接收的参数与其泛型相同。print() 和 format() 声明为 function(x, ...),因此它们的方法也以 x, ... 开头。... 可以接收额外参数,例如调用者可能传入的 digits。在调用泛型的任何地方都可以使用方法,例如在 vapply() 内部:
format.money <- function(x, ...) sprintf("%.2f %s", x$amount, x$currency)
wallet <- list(
structure(list(amount = 3, currency = "EUR"), class = "money"),
structure(list(amount = 0.5, currency = "USD"), class = "money")
)
print(vapply(wallet, format, character(1)))输出:
[1] "3.00 EUR" "0.50 USD"挑战
简单已提供 Money.R 中的 new_money()。在同一个文件中添加两个方法:
format.money(x, ...)返回金额和货币,金额保留两位小数:9.50 EUR。print.money(x, ...)使用format(),在单独一行打印<money 9.50 EUR>,并返回invisible(x)。
提供的代码会读取 9.5 EUR 这样的行,打印每个 money 对象,然后打印 list: ,其中包含用 + 连接的所有格式化金额。
你的代码写在 Money.R 中。main.R 中是提供的输入/输出代码,不能编辑。
亲手试试
source("Money.R")
# 提供的输入/输出代码:保持原样
input <- suppressWarnings(readLines(file("stdin")))
all <- list()
for (line in input) {
p <- strsplit(line, " ")[[1]]
m <- new_money(as.numeric(p[1]), p[2])
print(m)
all[[length(all) + 1]] <- m
}
cat("list: ", paste(vapply(all, format, character(1)), collapse = " + "), "\n", sep = "")
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: R 在线编译器