Обобщённые функции и UseMethod
Часть раздела Объектно-ориентированное программирование путешествия по R на Coddy. Урок 7 из 57.
Обобщённая функция — это функция, тело которой содержит UseMethod("name"). При вызове она проверяет класс своего первого аргумента и вызывает метод name.class. print() и format() работают именно так; вы также можете писать собственные обобщённые функции:
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))Вывод:
[1] "Rex says woof"
[1] "Tom says meow"Вызывающий код выполняет один вызов, и каждый объект отвечает по-своему. Это полиморфизм: коду, который перебирает смешанный список, не нужен if для каждого класса:
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")Вывод:
Rex says woof
Tom says meow
Bo says woof Метод получает аргументы обобщённой функции. Добавьте в обобщённую функцию параметр ..., чтобы методы могли принимать дополнительные аргументы, например 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))Вывод:
[1] 9
[1] 3.14
[1] 3.1416UseMethod() передаёт вызов методу и никогда не возвращается: всё, что возвращает метод, является результатом обобщённой функции, а код после UseMethod() не выполняется. Поэтому обобщённая функция состоит из одной строки:
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))Вывод:
[1] 10Задание
ЛегкоФигуры разделены по трём файлам. Реализуйте обобщённую функцию area() в Shape.R, затем добавьте методы area.circle() (пи, умноженное на радиус в квадрате) в Circle.R и area.rectangle() (ширина, умноженная на высоту) в Rectangle.R. Конструкторы предоставлены.
Предоставленный код считывает строки circle 2 или rectangle 3 4 и выводит класс и площадь каждой фигуры с двумя знаками после запятой: circle: 12.57.
Ваш код должен находиться в Shape.R, Circle.R и Rectangle.R. В main.R находится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
source("Shape.R")
source("Circle.R")
source("Rectangle.R")
# Предоставленный код ввода/вывода: оставьте его как есть
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 = "")
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы S3
Работа с файламиСписки с классомФункции-конструкторыМетоды print и formatВалидаторы и вспомогательные функцииПовторение — температуры4Инкапсуляция в R
Замыкания как объектыОкружения как объектыФункции доступаЗащита состоянияПовторение — парковочный счётчик7S4 Наследование
Расширение с помощью containscallNextMethodВиртуальные классыПроверка типов с помощью is()Повторение — смотритель зоопарка10Шаблоны проектирования, часть 2
Шаблон «Декоратор»Шаблон «Строитель»Шаблон «Состояние»Шаблон «Итератор»2Обобщённые функции и методы S3
Обобщённые функции и UseMethodМетоды по умолчаниюМетоды для базовых обобщённых функцийОсновы NextMethodПовторение — площади фигур5Классы S4
Определение классов S4Слоты и доступПроверка корректностиМетоды showПовторение — каталог товаров8Ссылочные классы
Определение ссылочных классовМетоды и обновление полейСемантика копированияНаследование и callSuperПовторение — очередь задач11Проект: Управление библиотекой
Книги и читателиВыдача книг3Наследование S3
Векторы классовПорядок поиска методовРасширение с помощью NextMethodПроверка с помощью inherits()Повторение — расчёт зарплаты сотрудниковПотренируйтесь самостоятельно: Онлайн-компилятор R