Menu
Coddy logo textTech

スロットとアクセス

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

obj@slot <- value はスロットを変更します。S3オブジェクトと同様に、S4オブジェクトは値です。つまり、オブジェクトを変更する関数はそのコピーに対して動作し、変更後のオブジェクトを返します。

setClass("Person", slots = c(name = "character", age = "numeric"))
birthday <- function(p) {
  p@age <- p@age + 1
  p
}
ada <- new("Person", name = "Ada", age = 36)
older <- birthday(ada)
cat(ada@age, older@age)

出力:

36 37

slot(obj, "name") はスロット名を文字列で指定した @ と同じ働きをするため、変数に格納された名前でも機能します。slotNames() はクラスまたはオブジェクトのスロットを一覧表示します。

setClass("Person", slots = c(name = "character", age = "numeric"))
ada <- new("Person", name = "Ada", age = 36)
for (s in slotNames(ada)) cat(s, "=", format(slot(ada, s)), "\n")
slot(ada, "age") <- 37
print(ada@age)

出力:

name = Ada 
age = 36 
[1] 37

すべての代入は、new() だけでなく、宣言された型に対してチェックされます。誤った値は拒否され、オブジェクトには元の値が保持されます。

setClass("Person", slots = c(name = "character", age = "numeric"))
ada <- new("Person", name = "Ada", age = 36)
ada@age <- "old"

出力:

Error in (function (cl, name, valueClass)  : 
  assignment of an object of class “character” is not valid for @‘age’ in an object of class “Person”; is(value, "numeric") is not TRUE
Execution halted

getSlots() は、宣言された型とともにすべてのスロット名を返すため、コードでテキスト入力をスロットが期待する型に変換できます。

setClass("Person", slots = c(name = "character", age = "numeric"))
types <- getSlots("Person")
print(types)
value <- "40"
if (types[["age"]] == "numeric") value <- as.numeric(value)
print(value + 1)

出力:

       name         age 
"character"   "numeric" 
[1] 41
challenge icon

チャレンジ

簡単

Profile クラスは Profile.R 内で、name と city(文字列)、および age(数値)のスロットを持ちます。2つの関数を完成させてください:

  • update_profile(p, field, value) は、フィールドがスロットでない場合に no field email で停止します(call. = FALSE を使用)。それ以外の場合、スロットが数値型ならテキスト value を as.numeric() で変換し、slot() でスロットを設定して、変更後のプロファイルを返します。
  • profile_lines(p) は、スロットの順序でスロットごとに1行を返します:name: Ada。

提供されたコードは名前を読み取り、続いて city=Paris または age=36 の行を読み取り、それぞれを適用して、プロファイルの各行を出力します。

コードは Profile.R に記述します。main.R には提供された入力/出力コードが含まれており、編集できません。

自分で試してみよう

source("Profile.R")

# 提供された入出力コード: そのままにしておく
input <- suppressWarnings(readLines(file("stdin")))
p <- new("Profile", name = input[1], city = "unknown", age = 0)
for (line in input[-1]) {
  kv <- strsplit(line, "=")[[1]]
  p <- tryCatch(update_profile(p, kv[1], kv[2]), error = function(e) {
    cat("error: ", conditionMessage(e), "\n", sep = "")
    p
  })
}
for (l in profile_lines(p)) cat(l, "\n", sep = "")
quiz icon腕試し

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

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

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