Я разработал класс S3 в R, который ведет себя очень похоже на фактор-переменную, хотя и не точно. Единственный snafu, который я оставил в моей реализации, заключается в том, что factor
и as.factor
не являются дженериками.Общие методы 'factor' и 'as.factor'
я обойти это ограничение для моего личного использования перекрывая base::factor
в функции .onload
в моем пакете следующим образом:
.onAttach <- function(libname,pkgname){
# note that as.factor is not a generic -- need to override it
methods:::bind_activation(on = TRUE)
# TODO: make a better attmept to deterime if base::factor is a generic or not.
if(!length(ls(pattern='^as\\.factor\\.default$', envir=as.environment('package:base'),all.names=TRUE))){
# bind the current implementation of 'as.factor' to 'as.factor.default'
assign('as.factor.default',
base:::as.factor,
envir=as.environment('package:base'))
# unock the binding for 'as.factor'
unlockBinding('as.factor', as.environment('package:base'))
# bind the generic to 'as.factor' in the 'package:base'
assign('as.factor',
function (x,...) UseMethod('as.factor') ,
envir=as.environment('package:base'))
# re-lock the binding for 'as.factor'
lockBinding('as.factor', as.environment('package:base'))
}
[similar code for making 'factor' and 'table' behave as generics excluded]
}
Однако я знаю изменения base
никогда бы не летать на CRAN, поэтому мне очень интересно если есть обходной путь. Как отмечает @BondedDust, я мог бы, конечно, переименовать мою функцию, которая отвечает за принуждение к обычным факторам (в настоящее время называется as.factor.MYCLASS
) примерно к As.factor
, но я бы предпочел не идти по этому маршруту, так как это означает, что пользователям придется писать код как это:
#coerce x to a factor
if(inherits(x,'MYCLASS'))
x <- As.factor(x)
else
x <- as.factor(x)
или
if(inherits(x,'MYCLASS'))
x <- Factor(x)
else
x <- factor(x)
Он просто чувствует себя странно, что принуждение к факторам не применяется в качестве общего.
Я также попробовал эту реализацию .onAttach
.onAttach <- function(libname,pkgname){
setOldClass(c("MYCLASS"),
where=as.environment('package:MyPackage'))
setMethod('factor',
signature(x='MYCLASS'),
factor.MYCLASS,
where=as.environment('package:MyPackage'))
}
Но я получаю сообщение об ошибке:
Error in rematchDefinition(definition, fdef, mnames, fnames, signature) :
methods can add arguments to the generic ‘factor’ only if '...' is an
потому что factor
не использует dots
аргумент и мой factor.MYCLASS
имеет один дополнительный аргумент.
Опытные разработчики пакетов, похоже, просто называют свои функции, связанные с классом, с другим, но похожим именем. Фрэнк Харрелл обычно капитализирует свои аналогичные, но не совсем те же функции ('Function',' Predict') или добавляет «2» в конец ('cut2'). –