R и объектно-ориентированное программирование

Объектно-ориентированное программирование так или иначе очень возможно в R. Однако, в отличие от, например, Python, существует много способов достижения объектной ориентации:

  • Пакет R.oo
  • Классы S3 и S4
  • Справочные classы
  • прото пакет

Мой вопрос:

Какие основные отличия различают эти способы программирования OO в R?

В идеале ответы здесь будут служить справочным материалом для программистов R, пытающихся решить, какие методы программирования OO наилучшим образом соответствуют их потребностям.

Таким образом, я прошу подробностей, представленных объективно, исходя из опыта и опираясь на факты и ссылки. Бонусные баллы за разъяснение того, как эти методы сопоставляются со стандартными методами ОО.

Классы S3

  • Не действительно объекты, больше соглашения об именах
  • Основано вокруг. синтаксис: например, для печати, print вызовов print.lm print.anova и т. д. И если не найден, print.default

S4 classы

  • Может отправлять по нескольким аргументам
  • Сложнее реализовать, чем S3

Справочные classы

  • В первую очередь полезно избегать создания копий больших объектов (передавать по ссылке)
  • Описание причин использования RefClasses

прото

  • ggplot2 был первоначально написан в прото, но в конечном итоге будет переписан с использованием S3.
  • Утонченная концепция (прототипы, а не classы), но кажется сложной на практике
  • Следующая версия ggplot2, похоже, отходит от нее
  • Описание концепции и реализации

R6 classы

  • По ссылке
  • Не зависит от classов S4
  • « Создание classа R6 аналогично эталонному classу, за исключением того, что нет необходимости разделять поля и методы, и вы не можете указывать типы полей».

Редактировать на 3/8/12: ответ ниже отвечает на часть первоначально размещенного вопроса, который с тех пор был удален. Я скопировал его ниже, чтобы предоставить контекст для моего ответа:

Как различные методы OO сопоставляются с более стандартными методами OO, используемыми, например, в Java или Python?


Мой вклад относится к вашему второму вопросу, о том, как методы O-O-R относятся к более стандартным методам OO. Как я уже думал об этом в прошлом, я возвращался снова и снова к двум отрывкам: одному Фридриху Лейшу, а другому – Джону Чемберсу. Оба делают хорошую работу по формулированию, почему программирование на OO в R имеет другой вкус, чем на многих других языках.

Во-первых, Фридрих Лейш из «Создание R-пакетов: учебник» ( предупреждение: PDF ):

S редок, потому что он одновременно интерактивен и имеет систему объектной ориентации. Проектирование classов явно является программированием, но для того, чтобы сделать S полезным в качестве среды интерактивного анализа данных, имеет смысл, что это функциональный язык. В «реальном» объектно-ориентированном программировании (ООП) языки, такие как определения classа C ++ или Java, тесно связаны друг с другом, методы являются частью classов (и, следовательно, объектов). Мы хотим инкрементных и интерактивных дополнений, таких как пользовательские методы для заранее определенных classов. Эти дополнения могут быть сделаны в любой момент времени, даже «на лету» в командной строке, когда мы анализируем dataset. S пытается сделать компромисс между объектной ориентацией и интерактивным использованием, и хотя компромиссы никогда не являются оптимальными в отношении всех целей, которые они пытаются достичь, они часто на удивление хорошо работают на практике.

Другой отрывок из превосходной книги Джона Чамберса «Программное обеспечение для анализа данных» . ( Ссылка на цитируемый отрывок ):

Модель программирования ООП отличается от языка S во всех, кроме первой, хотя S и некоторые другие функциональные языки поддерживают classы и методы. Определения методов в системе ООП являются локальными для classа; нет требования, чтобы одно и то же имя для метода означало одно и то же для несвязанного classа. Напротив, определения методов в R не находятся в определении classа; концептуально они связаны с общей функцией. Определения classов входят в определение выбора метода, непосредственно или через наследование. Программисты, используемые для модели ООП, иногда расстраиваются или путаются, что их программирование напрямую не передается на R, но это невозможно. Функциональное использование методов является более сложным, но также более приспособленным к содержательным функциям и не может быть сведено к версии ООП.

S3 и S4 кажутся официальными (т.е. встроенными) подходами для программирования OO. Я начал использовать комбинацию S3 с функциями, встроенными в конструкторскую функцию / метод. Моя цель состояла в том, чтобы иметь синтаксис типа объекта $ method (), так что у меня есть полу-частные поля. Я говорю полу-частный, потому что нет никакого способа их действительно скрывать (насколько я знаю). Вот простой пример, который на самом деле ничего не делает:

 #' Constructor EmailClass <- function(name, email) { nc = list( name = name, email = email, get = function(x) nc[[x]], set = function(x, value) nc[[x]] <<- value, props = list(), history = list(), getHistory = function() return(nc$history), getNumMessagesSent = function() return(length(nc$history)) ) #Add a few more methods nc$sendMail = function(to) { cat(paste("Sending mail to", to, 'from', nc$email)) h <- nc$history h[[(length(h)+1)]] <- list(to=to, timestamp=Sys.time()) assign('history', h, envir=nc) } nc$addProp = function(name, value) { p <- nc$props p[[name]] <- value assign('props', p, envir=nc) } nc <- list2env(nc) class(nc) <- "EmailClass" return(nc) } #' Define S3 generic method for the print function. print.EmailClass <- function(x) { if(class(x) != "EmailClass") stop(); cat(paste(x$get("name"), "'s email address is ", x$get("email"), sep='')) } 

И некоторый тестовый код:

  test <- EmailClass(name="Jason", "[email protected]") test$addProp('hello', 'world') test$props test class(test) str(test) test$get("name") test$get("email") test$set("name", "Heather") test$get("name") test test$sendMail("[email protected]") test$getHistory() test$sendMail("[email protected]") test$getNumMessagesSent() test2 <- EmailClass("Nobody", "[email protected]") test2 test2$props test2$getHistory() test2$sendMail('[email protected]') 

Вот ссылка на сообщение в блоге, которое я написал об этом подходе: http://bryer.org/2012/object-oriented-programming-in-r Я бы приветствовал комментарии, критические замечания и предложения к этому подходу, поскольку я не уверен если это лучший подход. Однако для проблемы, которую я пытался решить, она отлично поработала. В частности, для пакета makeR ( http://jbryer.github.com/makeR ) я не хотел, чтобы пользователи меняли поля данных напрямую, потому что мне нужно было убедиться, что XML-файл, представляющий состояние моего объекта, останется синхронным. Это работало отлично, пока пользователи придерживаются правил, изложенных в документации.

  • Как удалить элемент из списка?
  • Как создать матрицу корреляции в R?
  • Фильтровать фрейм данных по имени столбца символа (в dplyr)
  • Работа с neuralnet в R в первый раз: get "требует числовых / сложных матричных / векторных аргументов"
  • R: ggplot не работает, если он находится внутри цикла for, хотя он работает вне него
  • Настройка меток оси
  • Какие способы редактирования функции в R?
  • Передайте имя столбца data.frame в функцию
  • Как преобразовать Блестящее приложение, состоящее из нескольких файлов, в легкоansible и воспроизводимый пример Shiny?
  • Как отсортировать вектор символа, где элементы содержат буквы и числа в R?
  • Как преобразовать коэффициент в integer \ numeric без потери информации?
  • Давайте будем гением компьютера.