Окружения как объекты
Часть раздела Объектно-ориентированное программирование путешествия по R на Coddy. Урок 18 из 57.
Окружение — это набор именованных значений, например список, созданный с помощью new.env(). Отличие в том, что окружение никогда не копируется: каждая переменная, которая на него ссылается, видит тот же объект, поэтому изменение через одно имя видно через все остальные:
e <- new.env()
e$count <- 1
alias <- e
alias$count <- 99
print(e$count)
l <- list(count = 1)
copy <- l
copy$count <- 99
print(l$count)Результат:
[1] 99
[1] 1Функция, которая получает окружение, изменяет объект вызывающего кода. Ей не нужно ничего возвращать, и вызывающий код не присваивает результат:
deposit <- function(acc, x) acc$balance <- acc$balance + x
acc <- new.env()
acc$balance <- 10
deposit(acc, 5)
deposit(acc, 5)
print(acc$balance)Вывод:
[1] 20assign(), get() и exists() работают с именем, хранящимся в переменной, а ls() перечисляет имена в окружении в отсортированном порядке:
e <- new.env()
for (fruit in c("pear", "apple")) assign(fruit, nchar(fruit), envir = e)
print(ls(e))
print(get("pear", envir = e))
print(exists("kiwi", envir = e))Результат:
[1] "apple" "pear"
[1] 4
[1] FALSEСреда с атрибутом класса является объектом S3 с семантикой ссылок: её методы работают как обычно, а функции, которые изменяют её, делают это на месте:
new_wallet <- function(coins = 0) {
w <- new.env()
w$coins <- coins
class(w) <- "wallet"
w
}
print.wallet <- function(x, ...) {
cat("wallet with", x$coins, "coins\n")
invisible(x)
}
spend <- function(w, n) w$coins <- w$coins - n
w <- new_wallet(10)
spend(w, 3)
wВывод:
wallet with 7 coinsЗадание
ЛегкоИнвентарь представляет собой окружение класса inventory с одной переменной — items, именованным числовым вектором запасов. Дополните Inventory.R:
new_inventory()создаёт окружение с пустымitems(c()подходит) и классом.add_stock(inv, item, n)добавляетnк запасу товара, начиная с 0 для нового товара.take_stock(inv, item, n)удаляетnи возвращаетTRUE, когда запаса достаточно; в противном случае ничего не изменяет и возвращаетFALSE.stock_of(inv, item)возвращает запас, а для неизвестного товара — 0.
Функции изменяют инвентарь на месте и не возвращают его. Предоставленный код считывает команды add apple 5 и take apple 2, выводит результат каждой операции take, а затем каждый товар в алфавитном порядке.
Ваш код должен находиться в Inventory.R. В main.R содержится предоставленный код ввода/вывода, и его нельзя изменять.
Попробуйте сами
source("Inventory.R")
# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
inv <- new_inventory()
for (line in input) {
p <- strsplit(line, " ")[[1]]
n <- as.numeric(p[3])
if (p[1] == "add") add_stock(inv, p[2], n)
if (p[1] == "take") cat("take ", p[2], ": ", if (take_stock(inv, p[2], n)) "ok" else "not enough", "\n", sep = "")
}
for (item in sort(names(inv$items))) cat(item, ": ", stock_of(inv, item), "\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