callNextMethod
Часть раздела Объектно-ориентированное программирование путешествия по R на Coddy. Урок 33 из 57.
Внутри метода S4 callNextMethod() вызывает метод родительского класса с теми же аргументами и возвращает его результат. Метод дочернего класса использует ответ родительского метода вместо его повторения:
setClass("Employee", slots = c(name = "character", salary = "numeric"))
setClass("Manager", contains = "Employee", slots = c(reports = "numeric"))
invisible(setGeneric("describe", function(x) standardGeneric("describe")))
setMethod("describe", "Employee", function(x) paste(x@name, "earns", x@salary))
setMethod("describe", "Manager", function(x) paste(callNextMethod(), "and manages", x@reports))
print(describe(new("Manager", name = "Ada", salary = 60000, reports = 4)))Результат:
[1] "Ada earns 60000 and manages 4"То же самое работает и для show(): дочерний класс выводит строки родительского класса, а затем свои собственные:
setClass("Employee", slots = c(name = "character"))
setClass("Manager", contains = "Employee", slots = c(reports = "numeric"))
setMethod("show", "Employee", function(object) cat("Employee:", object@name, "\n"))
setMethod("show", "Manager", function(object) {
callNextMethod()
cat("Reports:", object@reports, "\n")
})
new("Manager", name = "Ada", reports = 4)Вывод:
Employee: Ada
Reports: 4 new() вызывает обобщённый метод initialize(). Метод для него может заполнить слоты, значения которых вычисляются на основе других слотов. Сначала он вызывает callNextMethod(.Object, ...), поэтому обычная настройка и проверка корректности по-прежнему выполняются:
setClass("Order", slots = c(prices = "numeric", total = "numeric"))
setMethod("initialize", "Order", function(.Object, ...) {
.Object <- callNextMethod(.Object, ...)
.Object@total <- sum(.Object@prices)
.Object
})
o <- new("Order", prices = c(2.5, 4, 1))
print(o@total)Вывод:
[1] 7.5Как и NextMethod() в S3, callNextMethod() проходит через несколько уровней, при этом каждый класс добавляет свою часть:
setClass("Ticket", slots = c(base = "numeric"))
setClass("Vip", contains = "Ticket")
setClass("Backstage", contains = "Vip")
invisible(setGeneric("price", function(t) standardGeneric("price")))
setMethod("price", "Ticket", function(t) t@base)
setMethod("price", "Vip", function(t) callNextMethod() * 2)
setMethod("price", "Backstage", function(t) callNextMethod() + 50)
cat(price(new("Ticket", base = 30)), price(new("Vip", base = 30)), price(new("Backstage", base = 30)))Результат:
30 60 110Задание
ЛегкоБилеты представлены в трёх уровнях, каждый в отдельном файле. Классы и обобщённая функция price() уже объявлены. Добавьте методы:
Ticket.R:price()возвращает базовую цену;show()выводитTicket for galaи перевод строки.Vip.R:price()возвращает цену билета, умноженную на 1.5;show()выводит строку билета, а затемVIP lounge access.Backstage.R:price()возвращает цену VIP-билета плюс 50;show()выводит строки VIP, а затемBackstage pass.
Используйте callNextMethod() в методах подклассов. Предоставленный код считывает строки vip gala 80 (уровень, событие, базовая цена) и выводит каждый билет и его цену.
Ваш код должен находиться в Ticket.R, Vip.R и Backstage.R. В main.R находится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
source("Ticket.R")
source("Vip.R")
source("Backstage.R")
# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
base <- as.numeric(p[3])
t <- switch(p[1],
standard = new("Ticket", event = p[2], base = base),
vip = new("VipTicket", event = p[2], base = base),
backstage = new("BackstageTicket", event = p[2], base = base))
print(t)
cat(sprintf("price: %.2f", price(t)), "\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