R и объектно-ориентированное программирование
Объектно-ориентированное программирование в той или иной мере очень возможно в R. Однако, в отличие от, например, Python, существует много способов достижения объектной ориентации:
Мой вопрос:
Какие основные различия различают эти способы программирования OO в R?
В идеале ответы здесь будут служить справочным материалом для программистов R, пытающихся решить, какие методы программирования OO наилучшим образом соответствуют их потребностям.
Таким образом, я прошу подробностей, представленных объективно, исходя из опыта и опираясь на факты и ссылки. Бонусные баллы за разъяснение того, как эти методы сопоставляются с стандартными методами OO.
Ответы
Ответ 1
классы S3
- На самом деле не объекты, больше соглашения об именах
- Основано на. синтаксис: например. для печати
print
вызывает print.lm
print.anova
и т.д. И если не найден, print.default
классы S4
Справочные классы
прото
- ggplot2 был первоначально написан в прото, но в конечном итоге будет переписан с использованием S3.
- Утонченная концепция (прототипы, а не классы), но на практике кажется сложной.
- Следующая версия ggplot2, похоже, отходит от нее.
- Описание концепции и реализации
Классы R6
- Байт-ссылка
- Не зависит от классов S4
- " Создание класс R6 похож на ссылочный класс, за исключением того, что нет необходимости отделять поля и методы, а вы не можете укажите типы полей."
Ответ 2
Изменить на 3/8/12:. Ответ ниже отвечает на часть изначально заданного вопроса, который с тех пор был удален. Я скопировал его ниже, чтобы предоставить контекст для моего ответа:
Как различные методы OO сопоставляются с более стандартными методами OO, используемыми, например, Java или Python?
Мой вклад относится к вашему второму вопросу о том, как методы R OO сопоставляются с более стандартными методами OO. Как я уже думал об этом в прошлом, я возвращался снова и снова к двум отрывкам: одному Фридриху Лейшу, а другому - Джону Чемберсу. Оба хорошо разбираются в том, почему OO-подобное программирование в R имеет другой вкус, чем на многих других языках.
Во-первых, Фридрих Лейш из "Создание R-пакетов: учебник" (предупреждение: PDF):
S редок, потому что он является одновременно интерактивным и имеет систему для объектной ориентации. Проектирование классов явно является программированием, но для того, чтобы сделать S полезным в качестве среды интерактивного анализа данных, имеет смысл, что это функциональный язык. В "реальном" объектно-ориентированном программировании (ООП) языки, такие как определения класса С++ или Java, тесно связаны друг с другом, методы являются частью классов (и, следовательно, объектов). Мы хотим инкрементных и интерактивных дополнений, таких как пользовательские методы для заранее определенных классов. Эти дополнения могут быть сделаны в любой момент времени, даже "на лету" в командной строке, когда мы анализируем набор данных. S пытается сделать компромисс между объектной ориентацией и интерактивным использованием, и хотя компромиссы никогда не являются оптимальными в отношении всех целей, которые они пытаются достичь, они часто на удивление хорошо работают на практике.
Другой отрывок из превосходной книги Джона Чамберса "Программное обеспечение для анализа данных" . (Ссылка на цитируемый фрагмент):
Модель программирования ООП отличается от языка S всего, кроме первого точка, хотя S и некоторые другие функциональные языки поддерживают классы и методы. Определения методов в системе ООП являются локальными для класса; нет требования, чтобы одно и то же имя для метода означало одно и то же вещь для несвязанного класса. Напротив, определения методов в R не находиться в определении класса; концептуально, они связаны с общим функция. Определения классов вводятся при определении выбора метода, непосредственно или через наследование. Программисты, используемые для модели ООП, иногда разочарованы или смущены тем, что их программирование напрямую не передается в R, но он не может. Функциональное использование методов является более сложным, но также более приспособлены к содержательным функциям и не могут быть сведены к Версия OOP.
Ответ 3
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"), " 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 файл, который представляемое мое состояние объекта будет оставаться в синхронизации. Это работало отлично, пока пользователи придерживаются правил, изложенных в документации.