Module 7: Exploring R’s Object Oriented Systems (S3 & S4)

GITHUB REPOSITORY: r-programming-assignments/Assignment_07.R at main · AustinTCurtis/r-programming-assignments 

Choose or Download Data

    • Load an existing dataset (e.g., data("mtcars")) or download/create your own.
    • Show the first few rows with head() and describe its structure with str().
R CODE:
# Built-in dataset
data("mtcars")

# Peek at the data
head(mtcars)
str(mtcars)

Test Generic Functions
    • Pick one or more base generic functions (e.g., print()summary()plot()).
    • Apply them to your dataset or an object derived from it.
    • If a generic does *not* dispatch on your object, explain *why* (e.g., no method defined for that class).
R CODE:
# These are all generics that dispatch methods based on class
print(mtcars)          # Uses print.data.frame
summary(mtcars)        # Uses summary.data.frame

# Derived an object
fit <- lm(mpg ~ hp + wt, data = mtcars)
class(fit)
summary(fit)           # summary.lm
print(fit)             # print.lm

Explore S3 vs. S4
  • Create an S3 object example:
    s3_obj <- list(name = "Myself", age = 29, GPA = 3.5)
    class(s3_obj) <- "student_s3"

R CODE:
# Created an S3 object
s3_obj <- list(name = "Myself", age = 29, GPA = 3.5)
class(s3_obj) <- "student_s3"

# Defined an S3 print() method
print.student_s3 <- function(x, ...) {
  cat(sprintf("S3 Student: %s (age %d), GPA = %.2f\n", x$name, x$age, x$GPA))
}

# Defined an S3 summary() method
summary.student_s3 <- function(object, ...) {
  out <- list(
    fields = names(object),
    numeric_fields = names(Filter(is.numeric, object)),
    gpa_ok = object$GPA >= 2.0
  )
  class(out) <- "summary.student_s3"
  out
}

# A print method for the *summary* result
print.summary.student_s3 <- function(x, ...) {
  cat("Fields:", paste(x$fields, collapse = ", "), "\n")
  cat("Numeric fields:", paste(x$numeric_fields, collapse = ", "), "\n")
  cat("GPA meets 2.0 threshold?:", x$gpa_ok, "\n")
}

print(s3_obj)      # dispatches to print.student_s3
summary(s3_obj)    # returns summary.student_s3 and then prints via its print() method

  • Create an S4 class and object example:
  • setClass("student_s4",
      slots = c(name = "character", age = "numeric", GPA = "numeric"))
    s4_obj <- new("student_s4", name = "Myself", age = 29, GPA = 3.5)
  • Demonstrate a generic function dispatch for each (e.g., write simple print methods).

R CODE:
# Loaded methods for S4 
library(methods)

# Defined an S4 class
setClass("student_s4",
         slots = c(name = "character", age = "numeric", GPA = "numeric")
)

# Created an S4 object
s4_obj <- new("student_s4", name = "Myself", age = 29, GPA = 3.5)

# For S4, "show" is the standard display generic
setMethod("show", "student_s4", function(object) {
  cat(sprintf("S4 Student: %s (age %d), GPA = %.2f\n",
              object@name, as.integer(object@age), object@GPA))
})

# Define a simple S4 generic and method
setGeneric("student_ok", function(x) standardGeneric("student_ok"))
setMethod("student_ok", "student_s4", function(x) x@GPA >= 2.0)

s4_obj          # triggers show()
student_ok(s4_obj)

Discussion Questions

On your blog, answer the following:

  • How can you tell whether an object uses S3 or S4? (Which functions inspect its class system?)
S3 objects usually have a "class" attribute and isS4(x) is FALSE. Check with class(x), attr(x, "class"), inherits(x, "foo"), and list methods via methods(class = class(x)). S4 objects return TRUE for isS4(x) and use formal definitions you can inspect with getClass("ClassName"), slotNames(x), validObject(x), and showMethods().

  • How do you determine an object’s underlying type (e.g., integer vs. list)?
typeof(x) → low-level storage type (e.g., "integer", "double", "list").
mode(x) / storage.mode(x) → higher-level representations.
str(x) → human-friendly structure and types.

  • What is a generic function in R?
A generic is a function that dispatches to a specific method based on an object’s class. In S3, a generic calls UseMethod("name") and finds name.class. In S4, a generic (created with setGeneric) dispatches to methods defined with setMethod using formal signatures.

  • What are the principal differences between S3 and S4 (e.g., method definition, formal class declarations)?
Class system:
S3: informal, class is just a string; no formal definition required.
S4: formal classes with declared slots (fields) and validation.

Method definition:

S3: define generic.class <- function(x, ...) {}; single dispatch on the first argument.
S4: setGeneric() + setMethod(); can dispatch on multiple argument classes.

Introspection/validation
S3: lightweight; fewer guarantees.
S4: strict; validObject(), slotNames(), getClass().

Typical usage
:
S3: most of base R and many packages (data frames, lm, etc.).
S4: Bioconductor and codebases needing stricter contracts.

Comments

Popular posts from this blog

Module #4 Visualizing and Interpreting Hospital Patient Data

Module # 2 Assignment Importing Data and Function Evaluation in R

Module 6: Matrix Operations and Construction