Advanced Functions/S3

Overview

Some functions in R are more complex than they first appear. We’ve looked at two such examples, summary and print. Both of these functions are actually generic functions which serve as coordinators for a number of different methods. In this way, a single function can accommodate several different input types, and other packages can make methods for their own object classes without messing with the original functions.

A hopefully helpful illustration
A hopefully helpful illustration

Today we are going to learn how to make our own generic functions and methods. This could potentially be helpful if you are dealing with common processes (like data extraction) for many different types of input (PDFs, webpages, etc.).

Adding Methods to Existing Generics

It is fairly simple to add a new method to an existing generic function. All you need to do is define a new function that adheres to the following format:

generic_function.class_name =
   function(x){
      When generic_function is called
      on an object of class
      class_name, do this to x.
}

So, if we wanted to add a new method to the summary() function for the “potato” class, I would define:

summary.potato =
   function(x){
      When summary is called
      on an object of class
      potato, do this to x.
}

Now, if I ever run summary() on an object which I have assigned the class “potato”, my new summary.potato() method will be used.

Creating a New Generic Function

How do we go about creating brand new generic functions? It’s actually pretty simple. Say I want to create a new generic function called “harvest”, which will work on classes of objects such as “strawberry”, “carrot”, and “apple”. To do so, all I need is:

harvest = function(x){ UseMethod(“harvest”) }

That’s it. We have a new generic function. Right now, it can’t do anything, as it has no methods associated with it. To add methods, you can follow the same process as what we did with summary().

Farming Methods

Run the following code in the console:

source("https://raw.githubusercontent.com/Adv-R-Programming/Adv-R-Reader/main/content/class_worksheets/26_adv_func/plant_function.R")

Then, run the new plant() function from your environment, assigning the output to a new object called field. It accepts "apple", "carrot", or "strawberry" as inputs.

The field object in your environment will have a class equal to whatever you input in the plant() function. Take the code from the last section and create a new generic harvest function, then create methods for objects with class “apple”, “carrot”, and “strawberry”. Your harvest methods should print out how many of the grown food items are present in your field (represented by a 1), and what kind of food it is.

You can peek at the code I used to make the plant() function by going to the web address inside the source() call above.

harvest.apple = function(x){

cat(“You have”, sum(x), class(x), “!”)

}