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?
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.
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.
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.
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.
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.
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