Home > Software design >  Can I overwrite the type of an S4 slot in R?
Can I overwrite the type of an S4 slot in R?

Time:09-09

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

  •  Tags:  
  • r s4
  • Related