Menu
CoddyTech

有效性检查

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

R 会检查类型,值的规则由你决定。setClass() 的 validity 参数是一个作用于 object 的函数:对象有效时返回 TRUE,否则返回描述问题的字符串。new() 会对每个对象运行这个函数:

setClass("Account", slots = c(owner = "character", balance = "numeric"),
  validity = function(object) {
    if (object@balance < 0) return("balance must not be negative")
    TRUE
  })
ok <- new("Account", owner = "Ada", balance = 10)
msg <- tryCatch(new("Account", owner = "Bo", balance = -5), error = function(e) conditionMessage(e))
cat(msg)

输出:

invalid class “Account” object: balance must not be negative

有效性函数可以通过返回字符向量,一次报告多个问题。R 会在错误消息中为它们编号:

setClass("Range", slots = c(lo = "numeric", hi = "numeric"),
  validity = function(object) {
    problems <- character(0)
    if (length(object@lo) != 1) problems <- c(problems, "lo must be one number")
    if (length(object@hi) != 1) problems <- c(problems, "hi must be one number")
    if (length(problems) == 0) TRUE else problems
  })
msg <- tryCatch(new("Range", lo = c(1, 2), hi = numeric(0)), error = function(e) conditionMessage(e))
cat(msg)

输出:

invalid class “Range” object: 1: lo must be one number
invalid class “Range” object: 2: hi must be one number

@<- 会检查类型,但不会运行有效性函数,因此赋值可能违反规则。validObject() 会再次运行检查;更改插槽后调用它:

setClass("Account", slots = c(balance = "numeric"),
  validity = function(object) if (object@balance < 0) "balance must not be negative" else TRUE)
a <- new("Account", balance = 10)
a@balance <- -99
cat("still created:", a@balance, "\n")
msg <- tryCatch(validObject(a), error = function(e) conditionMessage(e))
cat(msg, "\n")

输出:

still created: -99 
invalid class “Account” object: balance must not be negative 

R 会在你的文本前加上 invalid class “Account” object:。向用户显示消息的代码只需保留 object: 后面的部分:

setClass("Account", slots = c(balance = "numeric"),
  validity = function(object) if (object@balance < 0) "balance must not be negative" else TRUE)
msg <- tryCatch(new("Account", balance = -1), error = function(e) conditionMessage(e))
cat(sub(".*object: ", "", msg))

输出:

balance must not be negative
challenge icon

挑战

简单

在 Rating.R 中声明类 Rating,包含槽 stars(数值型)和 comment(字符型),并提供一个有效性函数,返回第一个不符合的规则:

  • 当 stars 不是 1、2、3、4、5 之一时,返回 stars must be a whole number from 1 to 5;
  • 当 comment 超过 20 个字符时,返回 comment is too long。

否则,返回 TRUE。提供的代码会读取 4;Great 这样的行(comment 可以缺省),创建每个评分,并打印 ok: 4/5 或问题文本。

你的代码写在 Rating.R 中。main.R 保存了提供的输入/输出代码,不能编辑。

亲手试试

source("Rating.R")

# 提供的输入/输出代码:保持原样
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, ";")[[1]]
  out <- tryCatch({
    r <- new("Rating", stars = as.numeric(p[1]), comment = if (length(p) > 1) p[2] else "")
    paste0("ok: ", r@stars, "/5")
  }, error = function(e) sub(".*object: ", "", conditionMessage(e)))
  cat(out, "\n", sep = "")
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: R 在线编译器