Menu
CoddyTech

Generics dan UseMethod

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan R di Coddy. Pelajaran 7 dari 57.

Generik adalah fungsi yang isi fungsinya berupa UseMethod("name"). Saat dipanggil, generik memeriksa class argumen pertamanya lalu memanggil method name.class. print() dan format() bekerja seperti ini. Kamu juga bisa menulis generik sendiri:

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))

Output:

[1] "Rex says woof"
[1] "Tom says meow"

Pemanggil menulis satu pemanggilan, dan setiap object menjawab dengan caranya sendiri. Inilah polimorfisme: kode yang melakukan perulangan pada list campuran tidak memerlukan if untuk setiap class:

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")

Output:

Rex says woof 
Tom says meow 
Bo says woof 

Sebuah method menerima argumen dari generic. Beri generic parameter ... agar method dapat menerima argumen tambahannya sendiri, seperti digits untuk lingkaran:

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))

Output:

[1] 9
[1] 3.14
[1] 3.1416

UseMethod() meneruskan pemanggilan ke method dan tidak pernah kembali: apa pun yang dikembalikan method menjadi hasil fungsi generik, dan kode setelah UseMethod() tidak dijalankan. Jadi, fungsi generik hanya terdiri dari satu baris:

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))

Keluaran:

[1] 10
challenge icon

Tantangan

Mudah

Bentuk dibagi ke dalam tiga file. Lengkapi fungsi generik area() di Shape.R, lalu tambahkan method area.circle() (pi dikali kuadrat jari-jari) di Circle.R dan area.rectangle() (lebar dikali tinggi) di Rectangle.R. Konstruktor sudah disediakan.

Code yang disediakan membaca baris circle 2 atau rectangle 3 4, lalu mencetak class dan luas setiap bentuk dengan dua angka desimal: circle: 12.57.

Tulis kodemu di Shape.R, Circle.R, dan Rectangle.R. main.R berisi code input/output yang disediakan dan tidak dapat diedit.

Coba sendiri

source("Shape.R")
source("Circle.R")
source("Rectangle.R")

# Kode input/output yang disediakan: biarkan apa adanya
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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler R online