R's S3 OO system is centered around generic functions that call methods depending on the class of the object the generic function is being called on. The crux is that the generic function calls the appropriate method, as opposed to other OO programming languages in which the method is defined within the class.
For example, the mean
function is a generic function.
isGeneric("mean")
methods(mean)
This will print
TRUE
[1] mean,ANY-method mean.Date mean.default mean.difftime
[5] mean.IDate* mean,Matrix-method mean.POSIXct mean.POSIXlt
[9] mean,sparseMatrix-method mean,sparseVector-method
see '?methods' for accessing help and source code
I was exploring R a bit and found the as
function. I am confused by the fact that R says the function is not generic, but it still has methods.
isGeneric("as")
methods(as)
TRUE
[1] as.AAbin as.AAbin.character
[3] as.alignment as.allPerms
[5] as.array as.array.default
[7] as.binary as.bitsplits
[9] as.bitsplits.prop.part as.call
...
At the end there is a warning that says that as
is not a generic.
Warning message:
In .S3methods(generic.function, class, parent.frame()) :
function 'as' appears not to be S3 generic; found functions that look like S3 methods
Could someone explain me what the as
function is and how is connected to as.list
, as.data.frame
etc? R says that as.list
is a generic (where I am tempted to get a bit mad at the inconsistencies within R, because I would expect as.list
to be a method for a list
object from the as
generic function). Please help.
as
is not an S3 generic, but notice that you got a TRUE. (I got a FALSE.) That means you have loaded a package that definesas
as an S4-generic. S3-generics work via class dispatch that employs a *.default
function and the UseMethod
-function. The FALSE I get means there is no method defined for a generic as
that would get looked up. One arguable reason for the lack of a generic as
is that calling such a function with only one data object would not specify a "coercion destination". That means the destination needs to be built into the function name.
After declaring as
to be Generic (note the capitalization which is a hint that this applies to S4 features:
setGeneric("as") # note that I didn't really even need to define any methods
get('as')
#--- output----
standardGeneric for "as" defined from package "methods"
function (object, Class, strict = TRUE, ext = possibleExtends(thisClass,
Class))
standardGeneric("as")
<environment: 0x7fb1ba501740>
Methods may be defined for arguments: object, Class, strict, ext
Use showMethods("as") for currently available ones.
If I reboot R (and don't load any libraries that call setGeneric for 'as') I get:
get('as')
#--- output ---
function (object, Class, strict = TRUE, ext = possibleExtends(thisClass,
Class))
{
if (.identC(Class, "double"))
Class <- "numeric"
thisClass <- .class1(object)
if (.identC(thisClass, Class) || .identC(Class, "ANY"))
return(object)
where <- .classEnv(thisClass, mustFind = FALSE)
coerceFun <- getGeneric("coerce", where = where)
coerceMethods <- .getMethodsTable(coerceFun, environment(coerceFun),
inherited = TRUE)
asMethod <- .quickCoerceSelect(thisClass, Class, coerceFun,
coerceMethods, where)
.... trimmed the rest of the code
But you ask "why", always a dangerous question when discussing language design, of course. I've flipped through the last chapter of Statistical Models in S which is the cited reference for most of the help pages that apply to S3 dispatch and find no discussion of either coercion or the as
function. There is an implicit definition of "S3 generic" requiring the use of UseMethod
but no mention of why as
was left out of that strategy. I think of two possibilities: it is to prevent any sort of inheritance ambiguity in the application of the coercion, or it is an efficiency decision.
I should probably add that there is an S4 setAs
-function and that you can find all the S4-coercion functions with showMethods("coerce")
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With