組み込み関数のメソッド
CoddyのRジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 28/57。
setMethod() は、length() や summary() などの基本関数にも S4 メソッドを追加します。基本関数はそれ以外のすべてに対して引き続き機能し、あなたのクラスには独自の動作が設定されます。
setClass("Playlist", slots = c(name = "character", songs = "character"))
setMethod("length", "Playlist", function(x) length(x@songs))
pl <- new("Playlist", name = "gym", songs = c("a", "b", "c"))
print(length(pl))
print(length(c(1, 2)))出力:
[1] 3
[1] 2演算子もジェネリックです。+ のメソッドでは、signature() に両辺のクラス名を指定します。2つの引数は e1 と e2 と呼ばれます。
setClass("Money", slots = c(amount = "numeric"))
setMethod("show", "Money", function(object) cat(sprintf("%.2f", object@amount), "\n"))
setMethod("+", signature("Money", "Money"), function(e1, e2) {
new("Money", amount = e1@amount + e2@amount)
})
new("Money", amount = 2.5) + new("Money", amount = 4)出力:
6.50 グループジェネリック Arith は、+、-、*、/、^ などを一度に表します。そのメソッド内では、callGeneric() が、渡した値に対して使用された演算子をそのまま繰り返します。
setClass("Money", slots = c(amount = "numeric"))
setMethod("Arith", signature("Money", "numeric"), function(e1, e2) {
new("Money", amount = callGeneric(e1@amount, e2))
})
m <- new("Money", amount = 10)
cat((m * 3)@amount, (m / 4)@amount, (m - 1)@amount)出力:
30 2.5 9グループジェネリック Compare は、==、<、> などを対象とします。そのメソッドはスロットに対して callGeneric() が返すもの、つまり論理値を返します:
setClass("Money", slots = c(amount = "numeric"))
setMethod("Compare", signature("Money", "Money"), function(e1, e2) {
callGeneric(e1@amount, e2@amount)
})
a <- new("Money", amount = 5)
b <- new("Money", amount = 8)
cat(a < b, a == b, a >= b)出力:
TRUE FALSE FALSEチャレンジ
簡単Money クラスには、Money.R 内にスロット amount(数値)と currency(文字列)があります。4 つのメソッドを追加してください:
show()は12.50 EURと改行を出力します。- 2 つの
Moneyオブジェクトに対する+はそれらの合計を返します。通貨が異なる場合は、call. = FALSEを使用してcannot add EUR and USDで停止します。 Moneyと数値に対する*は、金額をスケーリングした結果を返します。- 2 つの
Moneyオブジェクトに対する==は、金額と通貨の両方が等しい場合にTRUEになります。
提供されたコードは、10:EUR + 2.5:EUR、4:USD * 3、または 1:EUR == 1:EUR の行を読み取り、結果、または error: とエラーメッセージを出力します。
コードは Money.R に記述してください。main.R には提供された入出力コードが含まれており、編集できません。
自分で試してみよう
source("Money.R")
# 提供された入出力コード: そのままにしておく
input <- suppressWarnings(readLines(file("stdin")))
parse_money <- function(t) {
p <- strsplit(t, ":")[[1]]
new("Money", amount = as.numeric(p[1]), currency = p[2])
}
for (line in input) {
p <- strsplit(line, " ")[[1]]
a <- parse_money(p[1])
tryCatch({
if (p[2] == "+") print(a + parse_money(p[3]))
if (p[2] == "*") print(a * as.numeric(p[3]))
if (p[2] == "==") cat(a == parse_money(p[3]), "\n", sep = "")
}, error = function(e) cat("error: ", conditionMessage(e), "\n", sep = ""))
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rオンラインコンパイラ