-
Notifications
You must be signed in to change notification settings - Fork 755
Compared to S3, the S4 object system is much stricter, and much closer to other OO systems. I recommend you familiarise yourself with the way that S3 works before reading this document - many of underlying ideas are the same, but the implementation is much stricter.
There are two major differences from S3:
-
multiple dispatch: the generic function can be dispatched to a method based on the class of any number of argument, not just one
-
formal class definitions: unlike S3, S4 formally defines the representation and inheritance for each class
Here we introduce the basics of S4, trying to stay away from the esoterica and focussing on the ideas that you need to understand and write the majority of S4 code. If you would like to learn more, consult one of the more detailed resources such as: ...
In S3, you can turn any object into an object of a particular class just by setting the class attribute. S4 is much stricter: you must define the representation of the call using setClass
, and the only way to create it is through the constructer function new
.
A class has two key properties:
-
representation: a list of slots (or attributes), giving their names and classes. For example, a person class might be represented a character name and a numeric age, as follows:
representation(name = "character", age = "numeric")
-
a character vector of classes that it inherits from, or in S4 terminology, contains
setClass(name, representation, prototype, contains)
new(name, values) initialize
Can also define an optional method that applies additional restrictions. This function can also be specified in setClass
.
setValidity()
Accessing slots:
@
getSlot
getSlots
There's some tension between the usual interactive functional style of R and the global side-effect causing S4 class definitions. In most programming languages, class definition occurs at compile-time, while object instantiation occurs at run-time - it's unusual to be able to create new classes interactively. In particular, note that multiple calls to setClass
with the same class name will silently override the previous definition unless the first definition is sealed with sealed = TRUE
.
Generic functions and methods work similarly to S3, but dispatch is based on the class of all arguments, and there is a special syntax for creating both generic functions and new methods.
setGeneric(name, definition)
setMethod(method_name, signature, definition)
- callNextMethod
- inheritance
- setIs
- is, as as<-