Menu
Coddy logo textTech

Методы print и format

Часть раздела Объектно-ориентированное программирование путешествия по R на Coddy. Урок 4 из 57.

Когда значение выводится, R вызывает функцию print(). Если для класса не предусмотрено ничего особого, объект S3 выводится как его список, за которым следует атрибут класса, что трудно читать:

m <- structure(list(amount = 9.5, currency = "EUR"), class = "money")
print(m)

Вывод:

$amount
[1] 9.5

$currency
[1] "EUR"

attr(,"class")
[1] "money"

Метод — это функция с именем generic.class. Когда print() получает объект класса money, она ищет print.money() и вместо этого вызывает её. Метод печати записывает данные с помощью cat() и завершается вызовом invisible(x), поэтому возвращает объект, не выводя его второй раз:

print.money <- function(x, ...) {
  cat("<money ", x$amount, " ", x$currency, ">\n", sep = "")
  invisible(x)
}
m <- structure(list(amount = 9.5, currency = "EUR"), class = "money")
print(m)
m

Результат:

<money 9.5 EUR>
<money 9.5 EUR>

format() — это обобщённый способ преобразовать значение в текст. Метод format.money() возвращает текст, а не выводит его, поэтому другой код может вставить его в предложение, а метод печати — повторно использовать его:

format.money <- function(x, ...) {
  sprintf("%.2f %s", x$amount, x$currency)
}
print.money <- function(x, ...) {
  cat("Money:", format(x), "\n")
  invisible(x)
}
m <- structure(list(amount = 9.5, currency = "EUR"), class = "money")
m
cat("You owe", format(m), "\n")

Вывод:

Money: 9.50 EUR 
You owe 9.50 EUR 

Метод принимает те же аргументы, что и его обобщённая функция. print() и format() объявлены как function(x, ...), поэтому их методы тоже начинаются с x, .... ... принимает дополнительные аргументы, такие как digits, которые может передать вызывающий код. Методы работают везде, где вызывается обобщённая функция, например внутри vapply():

format.money <- function(x, ...) sprintf("%.2f %s", x$amount, x$currency)
wallet <- list(
  structure(list(amount = 3, currency = "EUR"), class = "money"),
  structure(list(amount = 0.5, currency = "USD"), class = "money")
)
print(vapply(wallet, format, character(1)))

Вывод:

[1] "3.00 EUR" "0.50 USD"
challenge icon

Задание

Легко

В Money.R задана функция new_money(). Добавь в этот же файл два метода:

  • format.money(x, ...) возвращает сумму с двумя знаками после запятой и валюту: 9.50 EUR.
  • print.money(x, ...) выводит <money 9.50 EUR> в отдельной строке, используя format(), и возвращает invisible(x).

Предоставленный код считывает строки 9.5 EUR, выводит каждый денежный объект, а затем выводит list: со всеми отформатированными суммами, соединёнными с помощью + .

Твой код должен находиться в Money.R. В main.R содержится предоставленный код ввода/вывода, и его нельзя изменять.

Попробуйте сами

source("Money.R")

# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
all <- list()
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  m <- new_money(as.numeric(p[1]), p[2])
  print(m)
  all[[length(all) + 1]] <- m
}
cat("list: ", paste(vapply(all, format, character(1)), collapse = " + "), "\n", sep = "")
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор R