Что означает «методы S3» в R?

125

Поскольку я новичок в R, я не знаю, что такое методы и объекты S3. Я обнаружил, что существуют объектные системы S3 и S4, и некоторые рекомендуют по возможности использовать S3 вместо S4 (см. Руководство по стилю R от Google по адресу http://google-styleguide.googlecode.com/svn/trunk/google-r-style. html ) *. Однако я не знаю точного определения методов / объектов S3.

Обновление: по состоянию на 2019 год гиперссылка на Google R Style Guide находится здесь .

jiggysoo
источник

Ответы:

85

Большую часть необходимой информации можно найти, просмотрев ?S3или ?UseMethod, но в двух словах:

S3 относится к схеме диспетчеризации методов. Если вы использовали R на некоторое время, вы заметите , что есть print, predictи summaryметоды много различных видов объектов.

В S3 это работает:

  • установка класса интересующих объектов (например: возвращаемое значение вызова метода glmимеет класс glm)
  • предоставляя метод с общим названием (например print), то точка, а затем имя класса (например: print.glm)
  • необходимо провести некоторую подготовку к этому общему имени ( print), чтобы это сработало, но если вы просто хотите соответствовать существующим именам методов, вам это не нужно (см. справку, на которую я ссылался ранее, если вы это сделаете ).

Для наблюдателя, и особенно для пользователя вашего недавно созданного пакета подгонки модных моделей, гораздо удобнее иметь возможность печатать, predict(myfit, type="class")чем predict.mykindoffit(myfit, type="class").

Это еще не все, но это должно помочь вам начать. У этого способа диспетчеризации методов, основанных на атрибуте (классе) объектов, есть немало недостатков (и пуристы C, вероятно, не спят по ночам в ужасе от этого), но для многих ситуаций он работает прилично. В текущей версии R были реализованы новые способы (S4 и эталонные классы), но большинство людей все еще (только) используют S3.

Ник Саббе
источник
55

Чтобы начать работу с S3, посмотрите на код medianфункции. Ввод medianв командной строке показывает, что в ее теле есть одна строка, а именно

UseMethod("median")

Это означает, что это метод S3. Другими словами, вы можете использовать разные medianфункции для разных классов S3. Чтобы перечислить все возможные медианные методы, введите

methods(median) #actually not that interesting.  

В этом случае есть только один метод по умолчанию, который вызывается для чего угодно. Вы можете увидеть код для этого, набрав

median.default

Гораздо более интересным примером является printфункция, у которой есть много разных методов.

methods(print)  #very exciting

Обратите внимание, что *рядом с именем некоторых методов стоит s. Это означает, что они скрыты внутри пространства имён некоторого пакета. Используйте, findчтобы узнать, в каком они пакете. Например

find("acf")  #it's in the stats package
stats:::print.acf
Ричи Коттон
источник
39

Из http://adv-r.had.co.nz/OO-essentials.html :

Три объектно-ориентированных системы R отличаются тем, как определены классы и методы:

  • S3 реализует стиль объектно-ориентированного программирования, называемый универсальной функцией OO. Это отличается от большинства языков программирования, таких как Java, C ++ и C #, которые реализуют объектно-ориентированный объект с передачей сообщений. При передаче сообщений сообщения (методы) отправляются объектам, и объект определяет, какую функцию вызывать. Обычно этот объект имеет особый вид при вызове метода, обычно появляющийся перед именем метода / сообщения: например, canvas.drawRect («синий»). S3 другой. Хотя вычисления по-прежнему выполняются с помощью методов, специальный тип функции, называемой универсальной функцией, решает, какой метод вызвать, например, drawRect (canvas, «синий»). S3 - очень обычная система. В нем нет формального определения классов.

  • S4 работает аналогично S3, но более формален. Есть два основных отличия от S3. S4 имеет формальные определения классов, которые описывают представление и наследование для каждого класса, а также специальные вспомогательные функции для определения универсальных шаблонов и методов. S4 также имеет множественную отправку, что означает, что универсальные функции могут выбирать методы на основе класса любого количества аргументов, а не только одного.

  • Эталонные классы, сокращенно RC, сильно отличаются от S3 и S4. RC реализует объектно-ориентированный режим передачи сообщений, поэтому методы принадлежат классам, а не функциям. $ используется для разделения объектов и методов, поэтому вызовы методов выглядят как холст $ drawRect ("синий"). Объекты RC также являются изменяемыми: они не используют обычную семантику R «копирование при изменении», а модифицируются на месте. Это затрудняет их рассуждение, но позволяет им решать проблемы, которые трудно решить с помощью S3 или S4.

Есть еще одна система, не совсем объектно-ориентированная, но о ней важно упомянуть здесь:

  • базовые типы, внутренние типы C-уровня, лежащие в основе других объектно-ориентированных систем. Базовыми типами в основном управляют с помощью кода C, но о них важно знать, поскольку они предоставляют строительные блоки для других объектно-ориентированных систем.
Амит К. Такур
источник
12

Я пришел к этому вопросу, в основном задаваясь вопросом, откуда взялись эти имена. Из этой статьи в Википедии видно, что это имя относится к версии языка программирования S, на которой основан R. Схемы диспетчеризации методов, описанные в других ответах, исходят от S и соответствующим образом помечены в соответствии с версией.

Джонатан Адельсон
источник
10

Пытаться

methods(residuals)

в котором перечислены, среди прочего, «остатки.lm» и «остатки.glm». Это означает, что если вы установили линейную модель, m и типresiduals(m), будут называться остатки.lm. Когда вы подобрали обобщенную линейную модель, будет вызвана остаточная сумма. Это своего рода объектная модель C ++, перевернутая с ног на голову. В C ++ вы определяете базовый класс, имеющий виртуальные функции, которые замещаются производными классами. В R вы определяете виртуальную (также известную как универсальную) функцию, а затем решаете, какие классы будут переопределять эту функцию (или определить метод). Обратите внимание, что классы, выполняющие это, не обязательно должны быть производными от одного общего суперкласса. Я бы не согласился вообще предпочитать S3 S4. В S4 больше формализма (= больше набора текста), и это может быть слишком много для некоторых приложений. Однако классы S4 могут быть определены как класс или структура в C ++. Вы можете указать, что объект определенного класса состоит из строки и двух чисел, например:

setClass("myClass", representation(label = "character", x = "numeric", y = "numeric"))

Методы, которые вызываются с объектом этого класса, могут полагаться на объект, имеющий эти члены. Это сильно отличается от классов S3, которые представляют собой просто список из набора элементов.

В S3 и S4 вы вызываете функцию-член по, fun(object, args)а не по object$fun(args). Если вы ищете что-то подобное, взгляните на пакет proto.

Харальд Брендель
источник
Я почти уверен, что идея функций-членов и методов, принадлежащих объектам, не имеет большого смысла в R. Методы не принадлежат объектам (также функции являются объектами), но принадлежат функции.
petermeissner
3

Вот обновленное краткое изложение многочисленных объектных систем R в соответствии с "Advanced R, 2nd edition" (CRC Press, 2019) Хэдли Уикхэм (главный научный сотрудник RStudio), веб-представление которого здесь основано на главе об объектах -Ориентированное программирование .

Обложка книги Advanced R

Первое издание 2015 года представлено здесь в Интернете , а соответствующая глава по объектно-ориентированному программированию находится здесь .

Подходы к ОО-системам

Хэдли определяет следующее, чтобы различать два разных подхода к объектно-ориентированному программированию:

Функциональное ООП : методы (вызываемые фрагменты кода) относятся к универсальным функциям (не путать с универсальными методами Java / C # ). Думайте о методах, как о находящихся в глобальной таблице поиска. Метод для выполнения определяется системой времени выполнения на основе имени функции и типа (или класса объекта) одного или нескольких аргументов, переданных этой функции (это называется «отправкой метода»). Синтаксис-накрест, вызовы методов могут выглядеть как обычные вызовы функций: myfunc(object, arg1, arg2). Этот вызов заставит среду выполнения искать метод, связанный с парой («myfunc», typeof (объект)) или, возможно, («myfunc», typeof (объект), typeof (arg1), typeof (arg2))если язык это поддерживает. В R S3 полное имя универсальной функции дает пару (имя-функция, класс) . Например: mean.Dateэто метод вычисления среднего числа дат. Попробуйте methods("mean")перечислить общие методы с именем функции mean. Функциональный подход ООП можно найти, например, в Smalltalk , пионере ООП , в объектной системе Common Lisp и в Julia . Хэдли отмечает, что «По сравнению с R, реализация Джулии полностью разработана и чрезвычайно эффективна».

Инкапсулированное ООП : методы принадлежат объектам или классам, и вызовы методов обычно выглядят так object.method(arg1, arg2). Это называется инкапсулированным, потому что объект инкапсулирует как данные (поля), так и поведение (методы). Подумайте о методе, который находится в таблице поиска, прикрепленной к объекту или описанию класса объекта. Среда выполнения ищет метод на основе имени метода и, возможно, типа одного или нескольких аргументов. Это подход, применяемый в «популярных» объектно-ориентированных языках, таких как C ++, Java, C #.

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

Как узнать, к какой системе принадлежит объект R

library(sloop) # formerly, "pryr"
otype(mtcars)
#> [1] "S3"

Объектные системы R

S3

  • Функциональный подход ООП.
  • Самая важная система по Хэдли.
  • Самый простой, самый распространенный. Первая объектно-ориентированная система, использованная Р.
  • Поставляется с базой R, используется во всей базе R.
  • Скорее полагается на условности, чем на принудительные гарантии.
  • См. Чемберс, Джона М. и Тревора Дж. Хасти. 1992. "Статистические модели в С." Уодсворт и Брукс / Продвинутые книги и программное обеспечение Коула.
  • Подробности в «Advanced R, 2-е издание» здесь .

S4

  • Функциональный подход ООП.
  • Третья по важности система по Хэдли.
  • Перепишите S3, следовательно, аналогично S3, но более формально и строго: это заставляет вас тщательно продумать дизайн программы. Подходит для создания больших систем (например, для проекта Bioconductor ).
  • Реализовано в базовом пакете "методы".
  • См .: Chambers, John M. 1998. «Programming with Data: A Guide to S Language». Springer.
  • Подробности в «Advanced R, 2-е издание» здесь .

RC aka "Референсные классы"

  • Инкапсулированный подход ООП.
  • Поставляется с базой R.
  • На основе S4.
  • RC-объекты - это особый тип объектов S4, которые также «изменяемы». т.е. вместо того, чтобы использовать обычную семантику R «копирование при изменении», они могут быть изменены на месте. Обратите внимание, что об изменяемом состоянии сложно рассуждать, и он является источником уродливых ошибок, но может привести к более эффективному коду в определенных приложениях.

R6

  • Инкапсулированный подход ООП.
  • Вторая по важности система по Хэдли.
  • Можно найти в пакете R6 (установить с помощью library(R6))
  • Подобен RC, но легче и намного быстрее: не зависит от S4 или пакета методов . Создан на основе среды R. Также имеет:
    • публичные и частные методы
    • активные привязки (поля, которые при доступе фактически вызывают метод)
    • наследование классов, которое работает между пакетами
    • оба метод класса (код , который принадлежит к классу и может получить доступ к экземпляру с помощью self, private, super) и функциями членов (функции , назначенные на поля, но которые не являются методами, только функция)
  • Предоставляет стандартизированный способ избежать семантики R "копирование при изменении"
  • См. Сайт пакета: «R6: Инкапсулированное объектно-ориентированное программирование для R» .
  • Подробности в «Advanced R, 2-е издание» здесь .

другие

Есть и другие, такие как R.oo (похожий на RC), proto (на основе прототипов, думаю, JavaScript) и Mutatr . Однако "Advanced R" говорит:

Помимо широко применяемого R6, эти системы представляют прежде всего теоретический интерес. У них есть свои сильные стороны, но немногие пользователи R знают и понимают их, поэтому другим трудно читать и вносить свой вклад в ваш код.

Не забудьте также прочитать главу о компромиссах в «Advanced R, 2nd edition» .

Дэвид Тонхофер
источник