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 withstr().
R CODE:
# Built-in dataset
data("mtcars")
# Peek at the data
head(mtcars)
str(mtcars)
- 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
- 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
printmethods).
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)?
S3: informal, class is just a string; no formal definition required.
S4: formal classes with declared slots (fields) and validation.
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().S3: most of base R and many packages (data frames, lm, etc.).
S4: Bioconductor and codebases needing stricter contracts.
Comments
Post a Comment