Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

does every S4 needs to be generic

Tags:

oop

r

s4

Suppose we have the following dummy class

Foo <- setClass(Class = "Foo",slots = c(foo = "numeric"), 
    prototype = list(foo = numeric())

I thought, generics are used to overload different functions. So assume we want to implement an accessor:

setMethod(f = "getFoo", signature = "Foo", 
    definition = function(Foo)
    {
        return(Foo@foo)
    }
)

Is this valid? Or do I have to define a generic first:

setGeneric(name="getFoo",
    def=function(Foo)
    {
        standardGeneric("getFoo")
    }
)

If there is just one particular "instance" of this function type, there is no reason to define a generic, correct?

like image 272
math Avatar asked May 06 '15 17:05

math


People also ask

Why do we need S4 classes?

Unlike S3 classes and objects which lacks formal definition, we look at S4 class which is stricter in the sense that it has a formal definition and a uniform way to create objects. This adds safety to our code and prevents us from accidentally making naive mistakes.

What is an S4 method?

S4 Methods. You can think of S4 methods as simple functions. A method is a function which can look at its arguments and decide what to do.

How are S4 classes better than S3 classes?

S4 Class is stricter, conventional, and closely related to Object-Oriented concepts. The classes are represented by the formal class definitions of S4. More specifically, S4 has setter and getter functions for methods and generics. As compared to the S3 class, S4 can be able to facilitate multiple dispatches.

What is S4 data type in R?

formal class definitions: unlike S3, S4 formally defines the representation and inheritance for each class. multiple dispatch: the generic function can be dispatched to a method based on the class of any number of argument, not just one.


1 Answers

In order to define an S4 method, there must be an existing S4 generic (either from base, imported from another package, or defined yourself). My understand of this design is to provide the flexibility to add on additional methods in the future, even if you can't even conceive of another one ATM.

That said, if you are just trying to be more concise you could just provide the default function directly to the generic function.

setClass(Class = "Foo",slots = c(foo = "numeric"), 
                prototype = list(foo = numeric()))

setGeneric(name="getFoo",
           def=function(Foo)
           {
               standardGeneric("getFoo")
           }, useAsDefault=function(Foo){return(Foo@foo)}
)

# test the function
testFoo <- new("Foo", foo=3)

getFoo(testFoo)
[1] 3

So, now you have your generic including the only functionality you really wanted anyway. You also have the option to add on the the generic in the future depending upon how your application develops.

like image 98
cdeterman Avatar answered Sep 23 '22 12:09

cdeterman