setValidity ve validObject
Coddy'nin R Journey'sinin Nesne Tabanlı Programlama bölümünün bir parçası. Ders 30 / 57.
setValidity("Class", function(object) ...), sınıf bildirildikten sonra geçerlilik kuralını ekler; bu da uzun bir setClass() çağrısını kısa tutar. setGeneric() gibi, en üst düzeyde yazdırılan bir değer döndürür; bu nedenle onu invisible() içine sarın:
setClass("Account", slots = c(owner = "character", balance = "numeric"))
invisible(setValidity("Account", function(object) {
if (object@balance < 0) return("balance must not be negative")
TRUE
}))
msg <- tryCatch(new("Account", owner = "Ada", balance = -1), error = function(e) conditionMessage(e))
cat(msg)Çıktı:
invalid class “Account” object: balance must not be negativeDeğişiklikler, sonucu denetleyen yöntemler aracılığıyla yapılmalıdır. Bir withdraw() yöntemi slot'u değiştirir, validObject() çağrısını yapar ve nesneyi yalnızca hâlâ geçerliyse döndürür:
setClass("Account", slots = c(balance = "numeric"))
invisible(setValidity("Account", function(object) {
if (object@balance < 0) "balance must not be negative" else TRUE
}))
invisible(setGeneric("withdraw", function(acc, amount) standardGeneric("withdraw")))
setMethod("withdraw", "Account", function(acc, amount) {
acc@balance <- acc@balance - amount
validObject(acc)
acc
})
a <- new("Account", balance = 50)
a <- withdraw(a, 20)
msg <- tryCatch({ a <- withdraw(a, 100); "done" }, error = function(e) "refused")
cat(msg, a@balance)Çıktı:
refused 30Bir erişimci çifti generiklerden oluşabilir: balance(x) okur ve bir değiştirme generiği olan "balance<-" yazar. Yöntemi nesneyi denetlediğinden, balance(a) <- -5 diğer tüm hatalı değişiklikler gibi reddedilir:
setClass("Account", slots = c(balance = "numeric"),
validity = function(object) if (object@balance < 0) "balance must not be negative" else TRUE)
invisible(setGeneric("balance", function(x) standardGeneric("balance")))
invisible(setGeneric("balance<-", function(x, value) standardGeneric("balance<-")))
setMethod("balance", "Account", function(x) x@balance)
setMethod("balance<-", "Account", function(x, value) {
x@balance <- value
validObject(x)
x
})
a <- new("Account", balance = 10)
balance(a) <- 25
msg <- tryCatch({ balance(a) <- -5; "changed" }, error = function(e) "refused")
cat(balance(a), msg)Çıktı:
25 refusedvalidObject(x, test = TRUE) durmaz. Geçerli bir nesne için TRUE veya bir rapor için kullanışlı olan sorun metnini döndürür:
setClass("Box", slots = c(w = "numeric"),
validity = function(object) if (object@w <= 0) "w must be positive" else TRUE)
b <- new("Box", w = 2)
print(validObject(b, test = TRUE))
b@w <- 0
print(validObject(b, test = TRUE))Çıktı:
[1] TRUE
[1] "w must be positive"Görev
KolayAccount.R içindeki Account sınıfı owner ve balance yuvalarına sahiptir. Dosyayı tamamlayın:
setValidity()ile (invisible()içine sarılmış)owner must not be emptyveyabalance must not be negativedöndüren bir kural ekleyin;deposit(acc, amount)vewithdraw(acc, amount)generic'lerini ve bunlarınAccountmetotlarını oluşturun:deposit, 0 veya daha küçük miktarlar içinamount must be positivehatasıyla durmalıdır (call. = FALSEkullanın); her ikisi de bakiyeyi değiştirmeli,validObject()çağırmalı ve hesabı döndürmelidir;ada: 50yazdıran ve yeni satıra geçen birshow()metodu ekleyin.
Sağlanan kod, hesabın sahibini ve ardından dep 50 veya wd 20 biçimindeki satırları okur; her değişiklikten sonra hesabı, aksi durumda refused: ifadesini ve sorunu yazdırır.
Kodunuz Account.R dosyasına yazılmalıdır. main.R, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.
Kendin dene
source("Account.R")
# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
input <- suppressWarnings(readLines(file("stdin")))
acc <- tryCatch(new("Account", owner = input[1], balance = 0),
error = function(e) { cat("error: ", sub(".*object: ", "", conditionMessage(e)), "\n", sep = ""); NULL })
if (!is.null(acc)) {
for (line in input[-1]) {
p <- strsplit(line, " ")[[1]]
amount <- as.numeric(p[2])
acc <- tryCatch({
changed <- if (p[1] == "dep") deposit(acc, amount) else withdraw(acc, amount)
print(changed)
changed
}, error = function(e) {
cat("refused: ", sub(".*object: ", "", conditionMessage(e)), "\n", sep = "")
acc
})
}
}
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ç Alma3S3 Kalıtımı
Sınıf VektörleriMetot Arama SırasıNextMethod ile Genişletmeinherits() ile DenetlemeÖzet - Personel Bordrosu6S4 Generic'leri ve Metotlar
Generic'ler OluşturmaYerleşik İşlevler için Metotlarİki Argümana Göre GönderimsetValidity ve validObjectÖzet - Para ve Para BirimiKendi başına pratik yap: Online R derleyicisi