Документация
R несколько сбивает с толку относительно того, является ли @
уже универсальным или нет: на странице справки для @
сказано, что это так, но его нет на странице internalGenerics
.
Оператор @
имеет специфическое поведение, а также (возможно) является универсальным. На странице справки для @
: «Проверено, что объект является объектом S4 (см. IsS4), и попытка использовать @ для любого другого объекта является ошибкой». Казалось бы, это исключает написание методов для классов S3, хотя в документации неясно, происходит ли эта проверка перед отправкой метода (если она есть) или после (откуда она может быть пропущена, если вы предоставили определенный метод для некоторого класса S3).
Вы можете реализовать то, что хотите, полностью переопределив, что такое @
, в соответствии с предложением в комментариях:
`@.default` <- function(e1,e2) slot(e1,substitute(e2))
но есть две причины не делать этого:
1) Как только кто-то загружает ваш пакет, он заменяет обычную функцию @
, поэтому, если люди вызывают его с другими объектами S4, они получают вашу версию, а не базовую версию R.
2) Эта версия значительно менее эффективна, чем внутренняя, и из-за (1) вы просто заставили ее использовать своих пользователей (если они не используют громоздкую конструкцию base::"@"(e1,e2)
). Эффективность может не иметь значения для вашего варианта использования, но может иметь значение для другого кода ваших пользователей, который использует S4.
Практически разумным компромиссом может быть определение собственного двоичного оператора %@%
и вызов метода по умолчанию @
. То есть
`%@%` <- function(e1,e2) slot(e1,substitute(e2))
setGeneric("%@%")
На практике это называется следующим образом:
> setClass("testClass",slots=c(a="character")) -> testClass
> x <- testClass(a="cheese")
> x %@% a
[1] "cheese"