Classes
Table of Contents
class
is similar to the class from other languagesmode
is a kind of atomic types
[1] "numeric"
NULL
[1] 10
[1] "logical"
[1] "numeric"
[1] "complex"
[1] "character"
> mean
function (x, ...)
UseMethod("mean")
OO Systems
- S3
drawRect(canvas, "blue")
dispatches the method call todrawRect.canvas("blue")
- S4
- similar to S3, but is more formal.
- Reference classes
- RC for short.
- like message-passing OO
- Looks like
canvas$drawRect("blue")
Currently S3 is the most popular one.
S3 object system
x <- 1
attr(x, "class") <- "foo"
x
# Or in one line
x <- structure(1, class = "foo")
x
# Or
class(x) <- "foo"
class(x)
[1] 1
attr(,"class")
[1] "foo"
[1] 1
attr(,"class")
[1] "foo"
[1] "foo"
mean <- function (x, ...) {
UseMethod("mean", x)
}
# Methods are ordinary functions that use a special naming convention: 'generic.class':
mean.numeric <- function(x, ...) sum(x) / length(x)
mean.data.frame <- function(x, ...) sapply(x, mean, ...)
mean.matrix <- function(x, ...) apply(x, 2, mean)
x <- structure(1, class = "foo")
bar <- function(x) UseMethod("bar", x)
bar.foo <- function(x) "hello"
bar(x)
[1] "hello"
- There are internal generics, methods implemented in C.
- Internal generic have a slightly different dispatch mechanism to other generic functions:
- Before trying the
default
method, they will also try dispatching on the mode of an object
- Before trying the
x <- structure(as.list(1:10), class = "myclass")
length(x) # this works even though there is no 'length.default'
# [1] 10
mylength <- function(x) UseMethod("mylength", x)
mylength.list <- function(x) length(x)
mylength(x)
# Error in UseMethod("mylength", x) :
# no applicable method for 'mylength' applied to an object of class
# "myclass"
Here is how inheritance works:
baz <- function(x) UseMethod("baz", x)
baz.A <- function(x) "A"
baz.B <- function(x) "B"
ab <- structure(1, class = c("A", "B"))
ba <- structure(1, class = c("B", "A"))
baz(ab)
baz(ba)
baz.C <- function(x) c("C", NextMethod())
ca <- structure(1, class = c("C", "A"))
cb <- structure(1, class = c("C", "B"))
baz(ca)
baz(cb)
[1] "A"
[1] "B"
[1] "C" "A"
[1] "C" "B"
baz <- function(x) UseMethod("baz", x)
baz.A <- function(x) {
print(c(.Generic, "(A)", .Class))
}
baz.B <- function(x) {
print(c(.Generic, "(B)", .Class))
NextMethod()
}
ba <- structure(1, class = c("B", "A"))
baz(ba)
[1] "baz" "(B)" "B" "A"
[1] "baz" "(A)" "A"