Menu
Coddy logo textTech

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.1416

UseMethod() ç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] 10
challenge icon

Gö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 = "")
}
quiz iconKendini test et

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

Kendi başına pratik yap: Online R derleyicisi