Search code examples
rcranr-s4

Test if S4 object is an instance


How do I test if an object is a instance of an S4 class (not sure if this is the right terminology)? I know about the function isS4 however, this also returns true for class definitions, etc. E.g.:

traj <- setClass(
  Class="Trajectories",
  representation=representation(
    times = "numeric",
    traj = "matrix"
  )
)

trajclass <- getClass("Trajectories")
trajobject <- new(Class="Trajectories",times=c(1,3),traj=matrix(1:4,ncol=2))

isS4(traj)
isS4(trajclass)
isS4(trajobject)

I am only interested in objects containing data, trajobject in this case; not so much in methods or class definitions. Is there a native function that I can use to test if an S4 object is an actual object? I.e. when using print(object) the output starts with:

An object of class "foo".....


Solution

  • S4 classes (and reference classes, for that matter and perhaps to the chagrin of some) are defined using S4 classes (cool (?) eh?)

    > class(trajclass)
    [1] "classRepresentation"
    attr(,"package")
    [1] "methods"
    > getClass(class(trajclass))
    Class "classRepresentation" [package "methods"]
    
    Slots:
    
    Name:             slots         contains          virtual        prototype
    Class:             list             list          logical              ANY
    
    Name:          validity           access        className          package
    Class: OptionalFunction             list        character        character
    
    Name:        subclasses       versionKey           sealed
    Class:             list      externalptr          logical
    
    Known Subclasses: "ClassUnionRepresentation", "refClassRepresentation"
    

    I think the best you could do is along the lines of

    isS4(trajclass) && !is(trajclass, "classRepresentation")
    

    S4 uses show as a synonym (sort of) for print; there is an S4 show method for classRepresentation that is

    > selectMethod(show, class(traj))
    Method Definition:
    
    function (object) 
    {
        cat(gettextf("Class generator function for class \"%s\" from package \"%s\"\n", 
            object@className, object@package))
        show(as(object, "function"))
    }
    <bytecode: 0x1522d40>
    <environment: 0xf1d808>
    
    Signatures:
            object                  
    target  "classGeneratorFunction"
    defined "classGeneratorFunction"
    

    whereas the show method for trajobject is the default, which is

    > selectMethod(show, class(trajobject))
    Method Definition (Class "derivedDefaultMethod"):
    
    function (object) 
    showDefault(object, FALSE)
    <bytecode: 0x1516d08>
    <environment: namespace:methods>
    
    Signatures:
            object        
    target  "Trajectories"
    defined "ANY"         
    

    with the meat in methods::showDefault. I guess you could implement

    setGeneric("isNotS4ClassDef",
        function(object) standardGeneric("isNotS4ClassDef"))
    
    setMethod(isNotS4ClassDef, "ANY",
        function(object) TRUE)
    
    setMethod(isNotS4ClassDef, "classRepresentation",
        function(object) FALSE)