Подтвердить что ты не робот

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

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

Мой вопрос:

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

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

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

4b9b3361

Ответ 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 файл, который представляемое мое состояние объекта будет оставаться в синхронизации. Это работало отлично, пока пользователи придерживаются правил, изложенных в документации.