Pewarisan dan callSuper
Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan R di Coddy. Pelajaran 40 dari 57.
contains = "Account" membuat Reference Class mewarisi setiap field dan method dari Account. Subclass menambahkan field dan method miliknya sendiri:
Account <- suppressMessages(setRefClass("Account",
fields = list(owner = "character", balance = "numeric"),
methods = list(deposit = function(x) balance <<- balance + x)
))
Savings <- suppressMessages(setRefClass("Savings", contains = "Account",
fields = list(rate = "numeric"),
methods = list(add_interest = function() deposit(balance * rate))
))
s <- Savings$new(owner = "Ada", balance = 100, rate = 0.05)
s$deposit(100)
s$add_interest()
cat(s$balance, is(s, "Account"))Output:
210 TRUESubclass melakukan override method dengan mendefinisikan method dengan nama yang sama. Di dalamnya, callSuper(...) memanggil versi milik parent, sehingga child hanya menambahkan hal yang baru:
Account <- suppressMessages(setRefClass("Account",
fields = list(balance = "numeric"),
methods = list(withdraw = function(x) {
if (x > balance) stop("insufficient funds", call. = FALSE)
balance <<- balance - x
})
))
Savings <- suppressMessages(setRefClass("Savings", contains = "Account",
methods = list(withdraw = function(x) {
if (x > 500) stop("limit is 500", call. = FALSE)
callSuper(x)
})
))
s <- Savings$new(balance = 300)
s$withdraw(200)
for (x in c(600, 400)) cat(tryCatch({ s$withdraw(x); "ok" }, error = function(e) conditionMessage(e)), "\n")
cat(s$balance, "\n")Output:
limit is 500
insufficient funds
100 initialize diwarisi dan di-override seperti method lainnya. initialize milik child memanggil callSuper(...) agar parent menetapkan field-nya, lalu menetapkan nilai defaultnya sendiri:
Account <- suppressMessages(setRefClass("Account",
fields = list(owner = "character", balance = "numeric"),
methods = list(initialize = function(...) {
initFields(...)
if (length(balance) == 0) balance <<- 0
invisible(.self)
})
))
Savings <- suppressMessages(setRefClass("Savings", contains = "Account",
fields = list(rate = "numeric"),
methods = list(initialize = function(...) {
callSuper(...)
if (length(rate) == 0) rate <<- 0.01
invisible(.self)
})
))
s <- Savings$new(owner = "Bo")
cat(s$owner, s$balance, s$rate)Output:
Bo 0 0.01Object dari subclass yang berbeda merespons pemanggilan method yang sama dengan caranya sendiri, jadi perulangan pada list campuran tidak memerlukan pemeriksaan class:
Account <- suppressMessages(setRefClass("Account",
fields = list(balance = "numeric"),
methods = list(month_end = function() balance <<- balance - 2)
))
Savings <- suppressMessages(setRefClass("Savings", contains = "Account",
methods = list(month_end = function() balance <<- balance * 1.01)
))
bank <- list(Account$new(balance = 100), Savings$new(balance = 100))
for (a in bank) a$month_end()
cat(vapply(bank, function(a) a$balance, numeric(1)))Output:
98 101Tantangan
MudahAkun dan rekening tabungan adalah Reference Class dalam dua file. Lengkapi method berikut:
AccountdiAccount.R(fieldowner,balance):initializemenetapkan balance ke 0 jika tidak diberikan;deposit(x);withdraw(x)berhenti denganinsufficient funds;month_end()mengenakan biaya sebesar 1;describe()mengembalikanada: 99.SavingsdiSavings.R(berisiAccount, fieldrate):withdraw(x)berhenti denganlimit is 500jika melebihi 500, dan jika tidak, memanggilcallSuper(x);month_end()menambahkan bunga,balance * rate, sebagai pengganti biaya;describe()menambahkan(savings)dengancallSuper().
Gunakan call. = FALSE. Kedua definisi dibungkus dalam suppressMessages(). Kode yang disediakan membaca savings ada 0.1 atau account bo, lalu dep 100, wd 30 atau month, dan mencetak describe() atau refused: beserta pesannya setelah masing-masing perintah.
Tuliskan kodemu di Account.R dan Savings.R. main.R berisi kode input/output yang disediakan dan tidak boleh diedit.
Coba sendiri
source("Account.R")
source("Savings.R")
# Kode input/output yang disediakan: biarkan apa adanya
input <- suppressWarnings(readLines(file("stdin")))
p <- strsplit(input[1], " ")[[1]]
acc <- if (p[1] == "savings") Savings$new(owner = p[2], rate = as.numeric(p[3])) else Account$new(owner = p[2])
for (line in input[-1]) {
q <- strsplit(line, " ")[[1]]
msg <- tryCatch({
if (q[1] == "dep") acc$deposit(as.numeric(q[2]))
if (q[1] == "wd") acc$withdraw(as.numeric(q[2]))
if (q[1] == "month") acc$month_end()
acc$describe()
}, error = function(e) paste("refused:", conditionMessage(e)))
cat(line, ": ", msg, "\n", sep = "")
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Object
1Dasar S3
Bekerja dengan fileList dengan classFungsi KonstruktorMethod print dan formatValidator dan helperUlasan: Suhu4Enkapsulasi di R
Closure sebagai objectEnvironment sebagai objectFungsi accessorMelindungi stateRangkuman: Meter Parkir2S3 Generics dan Method
Generics dan UseMethodMethod DefaultMethod untuk Base GenericsDasar-Dasar NextMethodRekap: Luas Bangun5S4 class
Mendefinisikan class S4Slots dan AksesPemeriksaan ValiditasMethod showRingkasan: Katalog Produk8Kelas Referensi
Mendefinisikan Kelas ReferensiPembaruan method dan fieldSemantik PenyalinanPewarisan dan callSuperRangkuman: Antrean Tugas11Proyek: Manajemen Perpustakaan
Buku dan AnggotaMeminjam BukuLatihan sendiri: Compiler R online