I want to create class in R, let's say it is an S4 class for a person. E.g.
setClass("Person", slots = list(name = "character", mood = "myMoodType"))
Now I want to create myMoodType
to be an abstract type that can only take the three values "Happy", "Sad" and "Unknown".
I know that I could do this using the validity for S4 classes and have the mood as a character type and check the validity by verifying that the character string provided is one of the three options I list. But I would like to know if I can define an abstract type, like in julia, e.g.
abstract myMoodType
type Happy <: myMoodType end
type Sad <: myMoodType end
type Unknown <: myMoodType end
What would be the correct way to approach this in R?
This might not be one of R's strongest and most smooth feature, but you could solve it in the following way. For more information see the documentation or the Advanced R chapter on S4.
First set up the Person class with the mood represented as a factor, and link it to a validation function that checks its levels.
check_person <- function(object) {
if(identical(levels(object@mood), c("Happy", "Sad", "Unknown"))){
return(TRUE)
} else {
return("Invalid mood.")
}
}
setClass("Person",
representation(name = "character", mood = "factor"),
prototype = list(name = NA_character_,
mood = factor(NA, c("Happy", "Sad", "Unknown"))),
validity = check_person)
Creating new instances with new
is however a bit messy since we have to write out all the levels each time:
john <- new("Person", name="John", mood=factor("Happy", levels=c("Happy", "Sad", "Unknown")))
lucy <- new("Person", name="Lucy", mood=factor("Sad", levels=c("Happy", "Sad", "Unknown")))
Otherwise we'll get an error:
new("Person", name="Eve", mood="Unknown")
Error in validObject(.Object) :
invalid class “Person” object: invalid object for slot "mood" in class "Person":
got class "character", should be or extend class "factor"
To get around that you could make your own constructor:
new_person <- function(name, mood){
new("Person", name = name, mood = factor(mood, levels = c("Happy", "Sad", "Unknown")))
}
new_person("Eve", "Unknown")
An object of class "Person"
Slot "name":
[1] "Eve"
Slot "mood":
[1] Unknown
Levels: Happy Sad Unknown