Menu
Coddy logo textTech

基本ジェネリックのメソッド

CoddyのRジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 9/57。

base R の多くの関数は S3 ジェネリックです:print()、format()、summary()、toString()、length()、as.character() などです。メソッドを追加すると、すべての R ユーザーがすでに知っている関数でクラスを扱えるようになります。summary.gradebook() はオブジェクト全体について報告します:

summary.gradebook <- function(object, ...) {
  paste0(length(object$marks), " marks, average ", mean(object$marks))
}
g <- structure(list(marks = c(70, 85, 91)), class = "gradebook")
cat(summary(g), "\n")

出力:

3 marks, average 82 

メソッドを書く前に、ジェネリックの引数を確認してください。summary() は最初の引数を object と呼びますが、toString() と format() は x と呼びます。toString() は単一の文字列を返す必要があります。

toString.gradebook <- function(x, ...) paste(x$marks, collapse = " / ")
g <- structure(list(marks = c(70, 85, 91)), class = "gradebook")
print(toString(g))

出力:

[1] "70 / 85 / 91"

length()メソッドは、クラスにおけるlength()の意味を変更します。フィールドに項目を格納するキューは、リスト内のフィールド数ではなく、保持している項目数を報告できます。

q <- structure(list(items = c("a", "b", "c"), name = "jobs"), class = "queue")
print(length(q))
length.queue <- function(x) length(x$items)
print(length(q))

出力:

[1] 2
[1] 3

演算子もジェネリックです。"+.money" という名前のメソッドは、記号を含むため引用符で囲まれており、+ のどちらか一方が money オブジェクトの場合に実行されます。これは両辺を e1 と e2 として受け取ります。

new_money <- function(amount) structure(list(amount = amount), class = "money")
"+.money" <- function(e1, e2) new_money(e1$amount + e2$amount)
"==.money" <- function(e1, e2) e1$amount == e2$amount
a <- new_money(5)
b <- new_money(7)
print((a + b)$amount)
print(a == b)

出力:

[1] 12
[1] FALSE
challenge icon

チャレンジ

簡単

スタックは項目をフィールド items に保持し、スタックのトップは最後の項目です。Stack.R には new_stack()、push()、pop() が用意されています。3つのメソッドを追加してください:

  • length.stack() は項目数を返します。
  • toString.stack() は項目をトップからボトムの順に | で結合して返します。項目がない場合は empty を返します。
  • summary.stack() は stack of 3, top: c を返します。空の場合は stack of 0 を返します。

用意されたコードは push <item> および pop コマンドを読み取り、長さ、toString()、summary() を出力します。

コードは Stack.R に記述してください。main.R には用意された入出力コードが含まれており、編集できません。

自分で試してみよう

source("Stack.R")

# 提供された入出力コード: そのままにしておく
input <- suppressWarnings(readLines(file("stdin")))
s <- new_stack()
for (cmd in input) {
  if (cmd == "pop") s <- pop(s) else s <- push(s, substring(cmd, 6))
}
cat("length: ", length(s), "\n", sep = "")
cat("items: ", toString(s), "\n", sep = "")
cat(summary(s), "\n", sep = "")
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Rオンラインコンパイラ