Menu
CoddyTech

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

UseMethod() ç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] 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() 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 = "")
}
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