クラスベクトル
CoddyのRジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 12/57。
S3の継承はクラスベクトルに由来します。class = c("manager", "employee")を持つオブジェクトはmanagerであり、同時にemployeeでもあります。ジェネリックにmanager用のメソッドがない場合、ディスパッチは次に進み、employeeメソッドを使用します。
pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
m <- structure(list(name = "Ada", salary = 60000), class = c("manager", "employee"))
print(class(m))
print(pay(m))出力:
[1] "manager" "employee"
[1] 5000各コンストラクターでクラスベクトルを手作業で記述すると、親の詳細が繰り返されます。代わりに、親コンストラクターが class 引数を受け取り、それを自身のクラスの前に置き、子コンストラクターが親コンストラクターを呼び出します。
new_employee <- function(name, salary, ..., class = character()) {
structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
new_manager <- function(name, salary, reports) {
new_employee(name, salary, reports = reports, class = "manager")
}
m <- new_manager("Ada", 60000, 4)
print(class(m))
print(names(m))出力:
[1] "manager" "employee"
[1] "name" "salary" "reports"親コンストラクターの...は子の追加フィールド(ここではreports)を集め、親自身のフィールドの後に配置します。通常の従業員にはreportsフィールドはまったくありません。
new_employee <- function(name, salary, ..., class = character()) {
structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
e <- new_employee("Bo", 40000)
print(class(e))
print(names(e))出力:
[1] "employee"
[1] "name" "salary"クラスベクトルの順序は重要です。最も具体的なクラスを最初に指定します。親クラスを先にすると、そのメソッドが優先され、子クラスのメソッドは決して使われません。
title <- function(x) UseMethod("title")
title.employee <- function(x) "employee"
title.manager <- function(x) "manager"
right <- structure(list(), class = c("manager", "employee"))
wrong <- structure(list(), class = c("employee", "manager"))
print(title(right))
print(title(wrong))出力:
[1] "manager"
[1] "employee"チャレンジ
簡単従業員とマネージャーは2つのファイルに分かれています。Employee.R の new_employee(name, salary, ..., class = character()) を完成させてください。この関数は、name、salary、および ... から渡された追加フィールドを含むリストを返し、クラスベクトルは c(class, "employee") とします。次に、Manager.R の new_manager(name, salary, reports) を完成させてください。この関数は、追加フィールド reports とクラス manager を指定して new_employee() を呼び出します。
label() とその employee メソッドは用意されているため、マネージャーは独自のメソッドがなくてもラベルを取得できます。提供されたコードは、employee Bo 40000 または manager Ada 60000 4 の行を読み取り、クラスベクトル、フィールド名、ラベルを出力します。
コードは Employee.R と Manager.R に記述します。main.R には提供された入力/出力コードが含まれており、編集できません。
自分で試してみよう
source("Employee.R")
source("Manager.R")
# 提供された入出力コード: そのままにしておく
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
x <- if (p[1] == "manager") new_manager(p[2], as.numeric(p[3]), as.numeric(p[4])) else new_employee(p[2], as.numeric(p[3]))
cat("class: ", paste(class(x), collapse = ", "), "\n", sep = "")
cat("fields: ", paste(names(x), collapse = ", "), "\n", sep = "")
cat(label(x), "\n", sep = "")
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rオンラインコンパイラ