Skip to content
S4 Classes
step 1/5

Reading — step 1 of 5

Learn

~1 min readS4 Classes and Functional Programming

R has multiple OO systems. S4 is the formal one — explicit slots, type-checked, multi-dispatch. Used heavily in Bioconductor.

# Define a class with slots:
setClass("Person",
    representation(
        name = "character",
        age = "numeric"
    ),
    prototype = list(name = "", age = 0)
)

# Construct:
ada <- new("Person", name = "Ada", age = 36)

# Access slots with @ (not $):
ada@name        # "Ada"
ada@age         # 36

# Update slots:
ada@age <- 37

S4 generic + methods:

setGeneric("greet", function(x) standardGeneric("greet"))

setMethod("greet", "Person", function(x) {
    sprintf("Hi, %s", x@name)
})

greet(ada)      # "Hi, Ada"

Multi-dispatch — method resolved by ALL arguments:

setGeneric("combine", function(a, b) standardGeneric("combine"))

setMethod("combine", signature("numeric", "numeric"), function(a, b) a + b)
setMethod("combine", signature("character", "character"), function(a, b) paste(a, b))

combine(3, 4)             # 7
combine("Hi", "World")    # "Hi World"

Dispatch checks class of each argument — different from S3 (which only checks the first).

Validity functions:

setValidity("Person", function(object) {
    if (object@age < 0) return("age cannot be negative")
    TRUE
})

new("Person", name = "Bob", age = -5)   # error

Inheritance with contains:

setClass("Employee",
    contains = "Person",
    representation(salary = "numeric"))

S4 vs S3:

  • S3 — informal, fast, used by base R (print, summary)
  • S4 — formal, slower, used when you need strict typing/multi-dispatch
  • R5/R6 — reference semantics (mutable objects), more like Java

For most data analysis: S3 is fine. Reach for S4 when you're building a library that needs proper class hierarchies and validation.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…