Kalıtım ve callSuper
Coddy'nin R Journey'sinin Nesne Tabanlı Programlama bölümünün bir parçası. Ders 40 / 57.
contains = "Account", bir Referans Sınıfının Account sınıfındaki her alanı ve yöntemi devralmasını sağlar. Alt sınıf kendi alanlarını ve yöntemlerini ekler:
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"))Çıktı:
210 TRUEBir alt sınıf, aynı ada sahip bir yöntem tanımlayarak bir yöntemi geçersiz kılar. İçinde callSuper(...), üst sınıfın sürümünü çağırır; böylece alt sınıf yalnızca yeni olanı ekler:
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")Çıktı:
limit is 500
insufficient funds
100 initialize diğer tüm metotlar gibi miras alınır ve geçersiz kılınır. Alt sınıfın initialize metodu, üst sınıfın alanlarını ayarlamasına izin vermek için callSuper(...) çağrısını yapar, ardından kendi varsayılanlarını ayarlar:
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)Çıktı:
Bo 0 0.01Farklı alt sınıflara ait nesneler aynı yöntem çağrısına kendi şekillerinde yanıt verir; bu nedenle karışık bir liste üzerinde yapılan bir döngünün sınıf kontrollerine ihtiyacı yoktur:
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)))Çıktı:
98 101Görev
KolayHesaplar ve tasarruf hesapları, iki dosyada bulunan Referans Sınıflarıdır. Metotları tamamlayın:
Account,Account.Riçinde (alanlarowner,balance):initialize, verilmediğinde bakiyeyi 0 olarak ayarlar;deposit(x);withdraw(x),insufficient fundsile durur;month_end(), 1 ücret alır;describe(),ada: 99döndürür.Savings,Savings.Riçinde (Accountiçerir,ratealanı):withdraw(x), 500'ün üzerindelimit is 500ile durur ve aksi takdirdecallSuper(x)çağırır;month_end(), ücret yerine faiz olanbalance * ratedeğerini ekler;describe(),callSuper()ile(savings)ekler.
call. = FALSE kullanın. Her iki tanım da suppressMessages() içine sarılır. Sağlanan kod savings ada 0.1 veya account bo okur, ardından dep 100, wd 30 ya da month komutunu işler ve her birinin ardından describe() ya da refused: ile mesajı yazdırır.
Kodunuz Account.R ve Savings.R dosyalarına gider. main.R, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.
Kendin dene
source("Account.R")
source("Savings.R")
# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
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 = "")
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Tabanlı Programlama bölümündeki tüm dersler
1S3 Temelleri
Dosyalarla ÇalışmaSınıf ile ListelerYapıcı FonksiyonlarPrint ve Format MetotlarıDoğrulayıcılar ve YardımcılarTekrar - Sıcaklıklar4R'da Kapsülleme
Nesne Olarak Closure'larNesne Olarak OrtamlarErişimci FonksiyonlarDurumu KorumaÖzet - Parkmetre2S3 Generic'leri ve Metotları
Generic'ler ve UseMethodVarsayılan MetotlarTemel Generic'ler için MetotlarNextMethod TemelleriTekrar - Şekil Alanları5S4 Sınıfları
S4 Sınıflarını TanımlamaSlotlar ve ErişimGeçerlilik KontrolleriShow MetotlarıÖzet - Ürün Kataloğu8Referans Sınıfları
Referans Sınıflarını TanımlamaMetotlar ve Alan GüncellemeleriKopyalama SemantiğiKalıtım ve callSuperÖzet - Görev Kuyruğu11Proje: Kütüphane Yönetimi
Kitaplar ve ÜyelerKitap Ödünç AlmaKendi başına pratik yap: Online R derleyicisi