R currently supports two internal OOP systems (S3 and S4), and several others as add-on packages, such as R.oo, and OOP.

S3 is easy to use but not reliable enough for large software projects. The S3 system emphasize on generic functions and polymorphism. It’s a function centric system which is different from class centric system like JAVA.

Computations are carried out by methods. In many OOP languages, that is, a call to obj.method() which will find the first ancestor class of obj that has a method .method(). R makes the same dicision in a different way, it turns the idea of inheritance “inside out”. In R, a special type of function called generic function decides which method to invoke. Methods are defined in the same way as a normal function, but with a tag describing what type of object they were designed to process.

Object Class

The class of an object is defined by a character vector of class names.

> x <- 1
> class(x) <- "foo"
#or 
> attr(x, "class") <- "foo"
#or
> x <- structure(1, class="foo")
> x
[1] 1
attr(,"class")
[1] "foo"

Objects can have many classes:

> class(x) <- c("foo", "bar")
> x
[1] 1
attr(,"class")
[1] "foo" "bar"

Generic functions and method dispatch

A generic function is a function that examines the class of its first argument, and thus decides which specific method to dispatch to.

Generic functions are defined by UseMethod with the generic name and the object to dispatch on as its parameters.

The following example shows how to define a generic function:

sound <- function(x) UseMethod("sound", x)

Methods are defined with a naming convention: generic.class:

sound.dog <- function(x) "bark"
sound.cow <- function(x) "moo"
sound.default <- function(x) "animal sound"

The methods function can find out which classes a generic function was designed for.

> methods("sound")
[1] sound.cow     sound.default sound.dog   

R looks for methods in the order in which they appear in the class vector until it found the appropriate method to operate on.

> x <- structure("cat", class = c("cat", "dog", "cow"))
> sound(x)
[1] "bark"

Inheritance

In S3 system, evaluation may be passed to a less specific method by calling NextMethod which provide a simple inheritance mechanism. NextMethod will dispatch on the second element of the class vector:

> class(x) <- c("dog", "cow")
> sound(x)
[1] "bark"
> sound.dog <- function(x) NextMethod()
> sound(x)
[1] "moo"