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?
There are two main types of abstract: the (1) Descriptive and the (2) Informative abstract.
An abstract class is a class that is declared abstract —it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed. When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class.
Abstract class: is a restricted class that cannot be used to create objects (to access it, it must be inherited from another class). Abstract method: can only be used in an abstract class, and it does not have a body. The body is provided by the subclass (inherited from).
A class which is declared as abstract is known as an abstract class. It can have abstract and non-abstract methods. It needs to be extended and its method implemented. It cannot be instantiated.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With