Generic'ler ve UseMethod
Coddy'nin R Journey'sinin Nesne Tabanlı Programlama bölümünün bir parçası. Ders 7 / 57.
Jenerik, gövdesi UseMethod("name") olan bir işlevdir. Çağrıldığında, ilk bağımsız değişkeninin sınıfına bakar ve name.class yöntemini çağırır. print() ve format() bu şekilde çalışır; siz de kendi jeneriklerinizi yazabilirsiniz:
speak <- function(x) UseMethod("speak")
speak.dog <- function(x) paste(x$name, "says woof")
speak.cat <- function(x) paste(x$name, "says meow")
rex <- structure(list(name = "Rex"), class = "dog")
tom <- structure(list(name = "Tom"), class = "cat")
print(speak(rex))
print(speak(tom))Çıktı:
[1] "Rex says woof"
[1] "Tom says meow"Çağrıyı yapan taraf tek bir çağrı yazar ve her nesne kendi yöntemiyle yanıt verir. Bu polimorfizmdir: farklı sınıflardan oluşan bir liste üzerinde döngü yapan kodun her sınıf için ayrı bir if kullanması gerekmez:
speak <- function(x) UseMethod("speak")
speak.dog <- function(x) paste(x$name, "says woof")
speak.cat <- function(x) paste(x$name, "says meow")
pets <- list(structure(list(name = "Rex"), class = "dog"),
structure(list(name = "Tom"), class = "cat"),
structure(list(name = "Bo"), class = "dog"))
for (p in pets) cat(speak(p), "\n")Çıktı:
Rex says woof
Tom says meow
Bo says woof Bir yöntem, generic'in argümanlarını alır. Generic'e bir ... parametresi verin; böylece yöntemler, bir daire için digits gibi kendilerine ait ek argümanları kabul edebilir:
area <- function(shape, ...) UseMethod("area")
area.square <- function(shape, ...) shape$side^2
area.circle <- function(shape, digits = 2, ...) round(pi * shape$r^2, digits)
sq <- structure(list(side = 3), class = "square")
ci <- structure(list(r = 1), class = "circle")
print(area(sq))
print(area(ci))
print(area(ci, digits = 4))Çıktı:
[1] 9
[1] 3.14
[1] 3.1416UseMethod() çağrıyı metoda devreder ve asla geri dönmez: metodun döndürdüğü değer generic'in sonucu olur ve UseMethod() sonrasındaki kod çalışmaz. Bu nedenle bir generic tek satırdan oluşur:
size <- function(x) {
UseMethod("size")
cat("this line never runs\n")
}
size.box <- function(x) x$w * x$h
b <- structure(list(w = 2, h = 5), class = "box")
print(size(b))Çıktı:
[1] 10Görev
KolayŞekiller üç dosyaya bölünmüştür. Shape.R içindeki genel area() işlevini tamamlayın, ardından Circle.R içinde area.circle() (pi çarpı yarıçapın karesi) ve Rectangle.R içinde area.rectangle() (genişlik çarpı yükseklik) yöntemlerini ekleyin. Yapıcılar verilmiştir.
Sağlanan kod circle 2 veya rectangle 3 4 satırlarını okur ve her şeklin sınıfını ve alanını iki ondalık basamakla yazdırır: circle: 12.57.
Kodunuz Shape.R, Circle.R ve Rectangle.R dosyalarına yazılmalıdır. main.R, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.
Kendin dene
source("Shape.R")
source("Circle.R")
source("Rectangle.R")
# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
s <- if (p[1] == "circle") new_circle(as.numeric(p[2])) else new_rectangle(as.numeric(p[2]), as.numeric(p[3]))
cat(sprintf("%s: %.2f", class(s), area(s)), "\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