Classes

Table of Contents

x <- 10
class(x)
unclass(x)  # remove temporarily the effects of class
[1] "numeric"
NULL
[1] 10
mode(TRUE)
mode(0)
mode(1i)
mode("foo")
[1] "logical"
[1] "numeric"
[1] "complex"
[1] "character"
> mean
function (x, ...)
UseMethod("mean")

OO Systems

S3
  • drawRect(canvas, "blue") dispatches the method call to drawRect.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"
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"