Векторы классов
Часть раздела Объектно-ориентированное программирование путешествия по R на Coddy. Урок 12 из 57.
Наследование S3 происходит из вектора классов. Объект с class = c("manager", "employee") является менеджером и одновременно сотрудником. Если для дженерика нет метода для manager, диспетчеризация продолжается и используется метод employee:
pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
m <- structure(list(name = "Ada", salary = 60000), class = c("manager", "employee"))
print(class(m))
print(pay(m))Результат:
[1] "manager" "employee"
[1] 5000Ручное указание вектора классов в каждом конструкторе повторяет сведения о родительском классе. Вместо этого родительский конструктор принимает аргумент class и помещает его перед своим собственным классом, а конструктор дочернего класса вызывает родительский:
new_employee <- function(name, salary, ..., class = character()) {
structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
new_manager <- function(name, salary, reports) {
new_employee(name, salary, reports = reports, class = "manager")
}
m <- new_manager("Ada", 60000, 4)
print(class(m))
print(names(m))Результат:
[1] "manager" "employee"
[1] "name" "salary" "reports"... конструктора родительского класса собирает дополнительные поля дочернего класса, в данном случае reports, и размещает их после собственных полей родительского класса. У обычного сотрудника поля reports вообще нет:
new_employee <- function(name, salary, ..., class = character()) {
structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
e <- new_employee("Bo", 40000)
print(class(e))
print(names(e))Результат:
[1] "employee"
[1] "name" "salary"Порядок вектора классов имеет значение: сначала указывается наиболее специфичный класс. Если сначала указать родительский класс, его методы будут иметь приоритет, а методы дочернего класса никогда не будут использованы:
title <- function(x) UseMethod("title")
title.employee <- function(x) "employee"
title.manager <- function(x) "manager"
right <- structure(list(), class = c("manager", "employee"))
wrong <- structure(list(), class = c("employee", "manager"))
print(title(right))
print(title(wrong))Результат:
[1] "manager"
[1] "employee"Задание
ЛегкоСотрудники и менеджеры разделены по двум файлам. Реализуйте new_employee(name, salary, ..., class = character()) в Employee.R: функция возвращает список с name, salary и всеми дополнительными полями из ..., с вектором классов c(class, "employee"). Затем реализуйте new_manager(name, salary, reports) в Manager.R. Эта функция вызывает new_employee() с дополнительным полем reports и классом manager.
label() и его метод employee уже предоставлены, поэтому менеджеры получают метку без собственного метода. Предоставленный код считывает строки employee Bo 40000 или manager Ada 60000 4 и выводит вектор классов, имена полей и метку.
Ваш код должен находиться в Employee.R и Manager.R. В main.R содержится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
source("Employee.R")
source("Manager.R")
# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
x <- if (p[1] == "manager") new_manager(p[2], as.numeric(p[3]), as.numeric(p[4])) else new_employee(p[2], as.numeric(p[3]))
cat("class: ", paste(class(x), collapse = ", "), "\n", sep = "")
cat("fields: ", paste(names(x), collapse = ", "), "\n", sep = "")
cat(label(x), "\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