If I have an S4 object like this:
obj1 <- setClass(
"obj1",
slots = c(
x = "numeric",
y = "numeric"
)
)
Is there a way to make a second object that inherits from obj1
but overwrites one of the data types of a slot? i.e.
obj2 <- setClass(
"obj2",
slots = c(
x = "character"
),
contains = "obj1"
)
CodePudding user response:
The documentation of setClass says :
The slots in a class definition will be the union of all the slots specified directly by slots and all the slots in all the contained classes. There can only be one slot with a given name. A class may override the definition of a slot with a given name, but only if the newly specified class is a subclass of the inherited one. For example, if the contained class had a slot a with class "ANY", then a subclass could specify a with class "numeric", but if the original specification for the slot was class "character", the new call to setClass would generate an error.
CodePudding user response:
The typical way to implement this would be to have both obj1
and obj2
inherit from a virtual class containing the common slots. This is particularly useful if you want to be able to call many of the same methods on both obj1
and obj2
.
Let's say we have the virtual class obj0
:
obj0 <- setClass(
"obj0",
slots = c(
y = "numeric"
),
contains = "VIRTUAL"
)
Then we can define the obj1
and obj2
classes with just the unique slots we want, while allowing them to inherit everything else from obj0
obj1 <- setClass(
"obj1",
slots = c(
x = "numeric"
),
contains = "obj0"
)
obj2 <- setClass(
"obj2",
slots = c(
x = "character"
),
contains = "obj0"
)
Creating an instance of each object type, we get the desired result for obj1
and obj2
obj1()
#> An object of class "obj1"
#> Slot "x":
#> numeric(0)
#>
#> Slot "y":
#> numeric(0)
obj2()
#> An object of class "obj2"
#> Slot "x":
#> character(0)
#>
#> Slot "y":
#> numeric(0)
And we don't need to worry about users trying to instantiate the incomplete obj0
class because they are disallowed:
obj0()
#> Error in new(structure("obj0", package = ".GlobalEnv"), ...):
#> trying to generate an object from a virtual class ("obj0")
Created on 2022-09-08 with reprex v2.0.2