Reputation: 5958
I have my s3 class student
# a constructor function for the "student" class
student <- function(n,a,g) {
# we can add our own integrity checks
if(g>4 || g<0) stop("GPA must be between 0 and 4")
value <- list(name = n, age = a, GPA = g)
# class can be set using class() or attr() function
attr(value, "class") <- "student"
value
}
stud <- student("name", 10, 3.5)
Now I would like to create a method similar to stud.doubleGPA()
which would double the GPA of the student. I know I can achieve this using
stud$GPA <- stud$GPA*2
stud$GPA # 7
However trying to define a function doesn't seem to work.
doubleGPA <- function(student) {
if(!class(student)=="student") stop("nope")
student$GPA <- student$GPA*2
}
doubleGPA(stud)
stud$GPA # 7 again (didn't work)
And replacing <-
with <<-
in the above function gives
Error in student$GPA <<- student$GPA * 2 :
object of type 'closure' is not subsettable
How can I define such a method which would belong to an s3 class and therefore be inherited by children ?
Cheers
Upvotes: 0
Views: 373
Reputation: 44877
You are thinking of a different kind of object oriented programming than the S3 style, something more like C++ or Java. You can do that in R, just not in the S3 system.
In the S3 system, methods "belong to" generic functions, not to classes. Like most functions in R, generic functions don't modify their arguments, they calculate new values and return those. So you might define a generic function doubleGPA()
, and have it work on the "student"
class using
doubleGPA <- function(x) UseMethod("doubleGPA")
doubleGPA.student <- function(x) {
x$GPA <- x$GPA*2
x
}
and then use it as
stud <- student("name", 10, 3.5)
stud <- doubleGPA(stud)
If you actually want something more like C++ or Java, there are a couple of choices: "reference classes" from the methods
package (see ?methods::setRefClass
) and "R6 classes" from the R6
package. There are also several prototype-based styles in packages proto
, ggplot2
, R.oo
, and are probably more that I've forgotten to mention.
Upvotes: 1