Why doesn't S4 accept default arguments on methods unless it is also set on the generic

Viewed 32

I was trying to set a default argument for my S4 method but found it only works if I also set a default value to the generic function. I was hoping someone could explain why this is happening as I would have expected this to work by just providing the default argument to the particular class definition?

myObj <- setClass(Class = "myObj", representation = list(x = "character"))

setGeneric(name = "myMeth", def = function(object, arg1) standardGeneric("myMeth"))

setMethod(
    f = "myMeth",
    signature = "myObj",
    definition = function(object, arg1 = "hello, world") {
        print(arg1)
    }
)

foo <- myObj()
myMeth(foo)

#> Error in print(arg1) : argument "arg1" is missing, with no default

Compared to:

setGeneric(name = "myMeth", def = function(object, arg1 = "") standardGeneric("myMeth"))

setMethod(
    f = "myMeth",
    signature = "myObj",
    definition = function(object, arg1 = "hello, world") {
        print(arg1)
    }
)

foo <- myObj()
myMeth(foo)

#> [1] "hello, world"
1 Answers

I believe the explanation goes like this:

  • R calls the generic more or less like any other function call. - Your generic declares that it has two arguments, object and arg1.
  • The generic looks at what was passed as its arguments to figure out the signature of the appropriate method to call.
  • Since your call to the generic didn't include arg1, you get the error message argument "arg1" is missing, with no default. It never considers calling the method, because it couldn't work out the appropriate signature, so it doesn't know about the default.

@AllanCameron in his comment gave a different design that probably does what you want to do: put ... in the generic instead of specifying arg1, which you want to be optional. Or do it as you did in your second version, with arg1 having a default value in the generic as well as the method.

Related