Создание обобщений
Часть раздела Объектно-ориентированное программирование путешествия по R на Coddy. Урок 27 из 57.
Обобщённая функция S4 создаётся с помощью setGeneric(). Её тело функции — standardGeneric("name"), аналог UseMethod() в S4. setGeneric() возвращает имя обобщённой функции, которое выводится при её вызове на верхнем уровне:
setGeneric("area", function(shape) standardGeneric("area"))Результат:
[1] "area"Оберните вызов в invisible(), чтобы эта строка не попала в вывод. Затем setMethod("area", "Circle", ...) добавляет метод для одного класса:
setClass("Circle", slots = c(r = "numeric"))
setClass("Square", slots = c(side = "numeric"))
invisible(setGeneric("area", function(shape) standardGeneric("area")))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
setMethod("area", "Square", function(shape) shape@side^2)
cat(area(new("Circle", r = 1)), area(new("Square", side = 3)))Вывод:
3.141593 9У метода те же аргументы, что и у его дженерика. Если дженерик содержит ..., метод может добавить после них собственные именованные аргументы:
setClass("Circle", slots = c(r = "numeric"))
invisible(setGeneric("describe", function(x, ...) standardGeneric("describe")))
setMethod("describe", "Circle", function(x, ..., digits = 2) {
paste("circle of area", round(pi * x@r^2, digits))
})
c1 <- new("Circle", r = 2)
print(describe(c1))
print(describe(c1, digits = 4))Результат:
[1] "circle of area 12.57"
[1] "circle of area 12.5664"setMethod() требует, чтобы обобщённая функция уже существовала, поэтому файл с setGeneric() сначала загружается. Вызов для класса без метода прекращается с ошибкой, в которой указана сигнатура:
invisible(setGeneric("area", function(shape) standardGeneric("area")))
setClass("Circle", slots = c(r = "numeric"))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
area(42)Результат:
Error: unable to find an inherited method for function ‘area’ for signature ‘shape = "numeric"’
Execution haltedЗадание
ЛегкоФигуры являются классами S4 в трёх файлах. В Shape.R создайте обобщённые функции area(shape) и perimeter(shape) с помощью setGeneric(), обернув их в invisible(). В Circle.R и Square.R объявлены классы; добавьте методы area и perimeter для каждого из них с помощью setMethod().
Предоставленный код считывает строки circle 2 или square 3 и выводит circle: area 12.57, perimeter 12.57.
Ваш код должен находиться в файлах Shape.R, Circle.R и Square.R. В main.R находится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
source("Shape.R")
source("Circle.R")
source("Square.R")
# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
s <- if (p[1] == "circle") new("Circle", r = as.numeric(p[2])) else new("Square", side = as.numeric(p[2]))
cat(sprintf("%s: area %.2f, perimeter %.2f", p[1], area(s), perimeter(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()Повторение — расчёт зарплаты сотрудников6S4: обобщения и методы
Создание обобщенийМетоды для встроенных объектовДиспетчеризация по двум аргументамsetValidity и validObjectПовторение — деньги и валютаПотренируйтесь самостоятельно: Онлайн-компилятор R