Generic'ler ve UseMethod
Coddy'nin R Journey'sinin Nesne Tabanlı Programlama bölümünün bir parçası. Ders 7 / 57.
Bir jenerik, gövdesi UseMethod("name") olan bir fonksiyondur. Çağrıldığında, ilk argümanının sınıfına bakar ve name.class metodunu çağırır. print() ve format() bu şekilde çalışır; kendi jeneriklerinizi de 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ğıran taraf tek bir çağrı yazar ve her nesne kendi yöntemiyle yanıt verir. Bu, çok biçimliliktir: karma bir liste üzerinde döngü yapan kodun her sınıf için ayrı bir if yazması 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. Yöntemlerin kendilerine ait ek argümanları kabul edebilmesi için generic'e bir ... parametresi verin; örneğin bir daire için digits:
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ı yönteme devreder ve asla geri dönmez: yöntemin döndürdüğü değer, jeneriğin sonucudur ve UseMethod() sonrasındaki kod çalışmaz. Bu nedenle jenerik 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() yöntemini (pi çarpı yarıçapın karesi) ve Rectangle.R içinde area.rectangle() yöntemini (genişlik çarpı yükseklik) 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