Generic functions in R are functions that can work differently based on the class of their arguments. Methods are the implementations of these generic functions for specific classes of objects.
There are two main systems for implementing generic functions and methods in R, they are S3 and S4.
In this article I’ll explain you both systems and provide a detailed working examples for each of them.
S3 Generic Functions and Methods
Generic Functions
In S3, generic functions are defined simply by creating a function with a special name convention.
The convention is to use a period (.) followed by the generic function name. For example, if you want to create a generic function called `plot`, you would name it `plot.`.
Methods
Methods in S3 are not formally defined or registered. Instead, they are created as functions that have the same name as the generic function they are associated with, followed by a period and the class of the object they operate on.
For example, if you want to create a method for the `plot` function for objects of class `data.frame`, you would name it `plot.data.frame`.
Let me write an example code which clearly shows the S3 functionality.
# Define the generic function plot. <- function(x, ...) { UseMethod("plot.") } # Define methods for specific classes plot.data.frame <- function(x, ...) { plot(x$y, x$x, ...) # Assume x is a data frame with columns x and y } plot.default <- function(x, ...) { plot(x, ...) } # Create some test data df <- data.frame(x = 1:10, y = rnorm(10)) # Test the generic function with different classes plot(df) # This should call plot.data.frame method plot(1:10) # This should call plot.default method
S4 Generic Functions and Methods
Generic Functions
In S4, generic functions are explicitly defined using the `setGeneric` function. This allows for a more formal and structured approach compared to S3.
Methods
Methods in S4 are formally defined and associated with generic functions using the `setMethod` function. You specify the function, the class it operates on, and the actual method implementation.
Now I’ll write an example code which explains the S4 functionality.
# Define a simple class setClass("MyClass", slots = c(x = "numeric", y = "numeric")) # Define a generic function setGeneric("plotS4", function(x, ...) { standardGeneric("plotS4") }) # Define a method for MyClass objects setMethod("plotS4", signature("MyClass"), function(x, ...) { plot(x@x, x@y, ...) }) # Create an object of MyClass obj <- new("MyClass", x = 1:10, y = rnorm(10)) # Test the generic function plotS4(obj)
In this example, `plotS4` is the generic function, and `plotS4.MyClass` is the method associated with the `MyClass` class. When you call `plotS4(obj)`, it calls the appropriate method for objects of class `MyClass`.
To be clear S3 and S4 provide different approaches for defining generic functions and methods in R. Each having its own strengths and use cases.
Keep in mind that S3 is simpler and more informal, while S4 is more formal and structured.
The choice between them depends on the specific requirements of your project. I would recommend you to be familiar with both S3 & S4 functionalities especially if you want to master R programming.