0% found this document useful (0 votes)
15 views49 pages

K32 Oop

The document discusses object-oriented programming concepts including classes, objects, properties, methods, inheritance, and how they relate to statistical concepts. It provides examples using a student class to illustrate key ideas like creating objects with constructors, accessing objects with getters and setters, and inheriting properties from general to special classes.

Uploaded by

DunsScoto
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views49 pages

K32 Oop

The document discusses object-oriented programming concepts including classes, objects, properties, methods, inheritance, and how they relate to statistical concepts. It provides examples using a student class to illustrate key ideas like creating objects with constructors, accessing objects with getters and setters, and inheriting properties from general to special classes.

Uploaded by

DunsScoto
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 49

Advanced R

Chapter 3.2: Object-oriented programming

Daniel Horn & Sheila Görz

Summer Semester 2022

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 1 / 49


Introduction to object-oriented programming

Introduction to object-oriented programming

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 2 / 49


Introduction to object-oriented programming

Object-oriented programming (OOP) is another programming paradigm


just like imperative programming. Whereas the latter concerns itself with
the question of ’what should to be done’, everything in OOP revolves
around data.
Often, many instances of data belong to an overarching whole. For
example, an iris plant can be described by the length and width of its
sepals and petals. Instead of keeping them separately in the memory,
they can be packaged.
Frequently, many such instances of data follow the same pattern. As
such, not only one plant can be observed, but multiple.
Usually, these related data can only change in a few well-defined ways,
e.g. iris plants can grow, wither or be picked.
Thus, everything revolves around data and how to manipulate it. Essential
to OOP are the terms ’Class’ and ’Object’ as well as ’Property’ and
’Method’.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 3 / 49


Introduction to object-oriented programming

Classes

Definition
A class is an abstract model/blueprint for a set of similar things. It
packages data (= properties) and methods into a single unit. The
properties and methods belonging to a class are specified in the definiton of
the respective class.

As an example for a class, consider the iris plants with the length and
width of the sepals and petals as its properties and the methods
’growing’, ’withering’ and ’being picked’.
Classes don’t have to be material things necessarily, e.g. the class of
real numbers in mathematics or the class of election forecasts.
A class never fully represents reality, but only the aspects relevant to the
given application. For example, the plant color doesn’t have to be a
property of the iris class.
Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 4 / 49
Introduction to object-oriented programming

Properties and methods

Property
Properties are the data of a class. Each property is provided with a name
and a range of values, e.g. the real numbers or the set {m, f}. However, no
actual values are assigned to the property yet. Properties only describe the
static state of a class.

Methods
Methods are the functions of a class. Methods can always access the values
of all properties. Further inputs as well as the output parameters of a
method are well-defined. Methods describe the dynamic behavior of a class.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 5 / 49


Introduction to object-oriented programming

Example: The student class


Over the course of this chapter, we’ll be looking at the examplary student
class from the examination office’s point of view. Obviously, a real student
has more properties and methods, but we’ll only cover the most relevant.
Class definition
Properties Methods
Name (character) getSemester: Calculate the
Student ID (integer) current semester

Beginning semester (date) addExamination: Add the result


of an exam
Achievements (data.frame):
Course (character)
getAverage: Calculate the
Module (character) current grade average
Weight (integer) hasFailed: Has the student
Grade (double) failed his studies?

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 6 / 49


Introduction to object-oriented programming

Objects

Objects are instances of classes. They fulfill the class definition, but can
hold differing values for the respective properties.

Example: Objects
Student 1 Student 2
Name: John Doe Name: Jane Doe
Student ID: 654321 Student ID: 1234
Beg. semester: 01.10.2016 Beg. semester: 01.04.2002
Achievements: Achievements:
Stats I BS I 0 2.0 LiMo BS IX 2 1.7
Analysis I BS III 0 3.3 Op. Res. BS X 1 5.0
Stats III BS VI 2 2.7 ... ... ... ...

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 7 / 49


Introduction to object-oriented programming

Methods and objects


Each method of the class can be called for each object of the class and
operates on the properties belonging to the respective object:

getSemester(Student 1) getSemester(Student 2)
3 32
getAverage(Student 1) getAverage(Student 2)
2.7 1.7

Objects can mutually call their methods, e.g. Student 1 could ask
Student 2 how long she has been studying for.
Thus, objects can communicate, make mutual inquiries and call for
each other’s ’services’.
In a pure OO-language no imperative programming occurs, but merely
communication between objects.
Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 8 / 49
Introduction to object-oriented programming

Similarities with statistics

The ideas behind a class and an object might seem familiar to us. After all,
they correspond to some statistical terms:

An object corresponds to an observation.


A property corresponds to a variable.
A class can most likely be found in the design of experiments when
we’re defining what we want to observe.
We don’t really have methods since we’re viewing data as static
objects.

This reflects how natural the idea of OOP is. However, since the state of a
computer program is dynamic (contrary to a static statistical data set), the
OOP approach is a bit more complex.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 9 / 49


Introduction to object-oriented programming

Creating an object

An object’s ’life’ begins upon its creation. To this end, the class provides a
so-called constructor function, usually denoted by new. In our example, we
would call a function named new.student():
student = new.student(Name = "Jonas Doe",
StudentID = 190920, BeginningSemester = "01.10.2017")

Objects can only be created by constructor functions.


The constructor function can only create valid students fulfilling the
class definition.
Thus: each student object fulfills the class definition.
Inside of the constructor, other things can happen as well, such as
checking for invalid inputs (e.g. future date as BeginningSemester) or
placing default values (Achievements = empty data.frame).

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 10 / 49


Introduction to object-oriented programming

Modifying an object: Getters and Setters

An object’s contents can’t be accessed arbitrarily: Only the object itself


knows the contents of its properties. To access them, we need to use
getter and setter methods.
getter functions
For each property of an object, a getter function can be defined which
merely returns the current value of the property.

setter functions
For each property of an object, a setter function can be defined which
sets the value of the property to a specified value.

Not every property has to be provided with a getter or a setter. For


example, the ID of a student is permanent and thus, there should be no
setter for it. Properties without a getter are invisible to the outside.
Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 11 / 49
Introduction to object-oriented programming

Inheritance I

The last central component of object-oriented programming we’ll be


looking at is inheritance. Often times, classes are closely related, e.g:
The class of iris plants is a subclass of flowers. All flowers have sepals
and petals, they all grow and wither.
In particular, there are two types of relations:
1 A class can generalize another class.
2 A class can be a special case of another class.
These findings closely resemble the world of animals and plants: Mammals
share many common properties (general class), while individual animal
species specialize them further (special classes).

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 12 / 49


Introduction to object-oriented programming

Inheritance II

The special class inherits the properties of the general class:


The special class possesses all properties of the general class.
The special class can have additional properties as well.
The special class possesses all methods of the general class. Their
implementation can, however, differ to account for the more special
behavior.
The special class can have additional methods.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 13 / 49


Introduction to object-oriented programming

Inheritance: Example

Consider these four classes specializing the general student class: B.Sc.
Statistics, M.Sc. Statistics, B.Sc. Data Science, M.Sc. Data Science
The master degree classes, for example, have the date of the
bachelor’s graduation as an additional property.
The implementation of the method addExamination() differs in
particular:
It throws an error when an invalid achievement is added, e.g. Statistics
I for M.Sc. courses
The respective weights of the modules differ between the Statistics and
Data Science study programs because the grade is calculated differently
However, some methods are identical, e.g.: determining the current
semester count.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 14 / 49


Introduction to object-oriented programming

Object-oriented programming in R
OOP contains many more details that have been covered in countless
(bulky) books. Various programming languages implement the respective
components of OOP in different ways. R supports OOP as well and even
offers four different systems:
Base types: We’ve already covered classes, constructors, etc. of basic
data types extensively in Chapter 2.1. We’re able to use this system,
but we can’t define our own classes.
S3: Though being the oldest and most minimal, it’s also the most
flexible and most used OO-system in R. It’s used in particular inside
the base package, but it only supports some the presented concepts.
S4: Extends S3 in many places, but also loses a lot of its flexibility in
result. Can be found in some CRAN packages. Its trademark is the @.
Reference Class (RC): It’s only used seldomly, but actually resembles
the OOP concepts presented so far the most.
Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 15 / 49
Object-oriented programming in R: The S3 system

Object-oriented programming in R: The S3 system

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 16 / 49


Object-oriented programming in R: The S3 system

Objects in R

Recalling Paradigm 1 from the chapter on data types:


Paradigm 1
Everything in R is an object.

We can retrieve the class of an object by using the class() function:


class(2) class(iris)

## [1] "numeric" ## [1] "data.frame"

class("a name") class(table(iris$Species))

## [1] "character" ## [1] "table"

numeric and character belong to the base types. data.frame and


table, however, are S3 objects which we’ll cover next.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 17 / 49


Object-oriented programming in R: The S3 system

S3 objects

An object in R is an S3 object when a value has been assigned to its class


attribute. This value is then the object’s class.

names(attributes(iris)) names(attributes(table(iris$Species)))

## [1] "names" "class" "row.names"## [1] "dim" "dimnames" "class"

attr(iris, "class") attr(table(iris$Species), "class")

## [1] "data.frame" ## [1] "table"

Thus, in the case of an S3 object, class() only returns the attribute’s


value. Contrary to names() for example, class() also returns a value
different from NULL when the attribute is missing. As for the three other
OO systems, an object’s class is determined differently.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 18 / 49


Object-oriented programming in R: The S3 system

Class definitions in S3 I

The most important simplification of S3 is the absence of formal class


definitions. Instead, an object can be assigned to a class simply by placing
the class attribute:
x = 1:5
class(x) = "myClass"

The properties of the myClass class are defined nowhere.


Whether or not x is a valid object of the myClass class is never
checked. After all, there doesn’t even exist a class definition for it.
Consequently, any object can be assigned to any class. Nobody checks
on us or keeps us from doing so.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 19 / 49


Object-oriented programming in R: The S3 system

Class definitions in S3 II

Also, nobody keeps us from modifying the class of an existing object either.
However, this is generally not advisable. Sometimes we get an error,
sometimes things can get out of control.

x = 1:4 x = 1:4
class(x) = "factor" class(x) = "data.frame"
x x

## Error in as.character.factor(x): ## NULL


malformed factor ## <0 rows> (or 0-length row.names)

Through the class affiliation of S3 objects, R offers us an powerful weapon


which we can use to modify everything as we please. However, it’s not
sensible to point this weapon at our own foot and pull the trigger.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 20 / 49


Object-oriented programming in R: The S3 system

Creating our own objects in R I

When we want to create an object of our student class, we simply have to


add the respective class attribute to an R object. What kind of R objects
are suited for this?
1 Named lists: Each list element corresponds to a property. List elements
can be named and can store arbitrary contents. Thus, the
requirements would be fulfilled.
x = list(Name = "John Doe", StudentID = 123456L,
BeginningSemester = ISOdate(2013, 10, 01), Achievements = data.frame())
class(x) = "student"
str(x)
## List of 4
## $ Name : chr "John Doe"
## $ StudentID : int 123456
## $ BeginningSemester: POSIXct[1:1], format: "2013-10-01 12:00:00"
## $ Achievements :'data.frame': 0 obs. of 0 variables
## - attr(*, "class")= chr "student"

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 21 / 49


Object-oriented programming in R: The S3 system

Creating our own objects in R II

2 (Almost) any arbitrary R object: In this case, we can store the


properties inside the object’s attributes. Some property names are
forbidden though (e.g. class) and the contents of the ’master object’
remain.
x = "Student 1"
attributes(x) = list(Name = "John Doe", StudentID = 123456L,
BeginningSemester = ISOdate(2013, 10, 01), Achievements = data.frame())
class(x) = "student"
str(x)
## 'student' chr "Student 1"
## - attr(*, "Name")= chr "John Doe"
## - attr(*, "StudentID")= int 123456
## - attr(*, "BeginningSemester")= POSIXct[1:1], format: "2013-10-01 12:00:00
## - attr(*, "Achievements")='data.frame': 0 obs. of 0 variables

In particular, x can also be a function and be called via x().

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 22 / 49


Object-oriented programming in R: The S3 system

Constructors in S3 I

Even though they don’t always exist and we’re not obliged to use them,
many S3 classes from the base package offer constructor functions.

factor() data.frame()

## factor(0) ## data frame with 0 columns and 0 rows


## Levels:

These functions always return valid S3 objects of the respective class.


Thus, we should preferably make use of these already existing constructors.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 23 / 49


Object-oriented programming in R: The S3 system

Constructors in S3 II

We should also define a constructor for our student class. To do this, we’re
using structure() to create a list and place the class attribute directly.
new.student = function(Name, StudentID, BeginningSemester) {
feats = list(Name = Name, StudentID = StudentID,
BeginningSemester = BeginningSemester, Achievements = NULL)
structure(feats, class = "student")
}
stud = new.student("John Doe", 123456L, ISOdate(2013, 10, 01))
str(stud)

## List of 4
## $ Name : chr "John Doe"
## $ StudentID : int 123456
## $ BeginningSemester: POSIXct[1:1], format: "2013-10-01 12:00:00"
## $ Achievements : NULL
## - attr(*, "class")= chr "student"

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 24 / 49


Object-oriented programming in R: The S3 system

Generic methods

Up until now, we have only talked about S3 objects and properties while
completely ignoring methods. For a good reason: S3 objects only contain
properties. Contrary to many other programming languages, methods are
not a compontent of objects.

Instead, R follows the principle of generics:

Generics
Methods don’t belong to objects, but to distinctly defined functions,
so-called generics. To call a method, the generic function must first be
called with the object as its input parameter. The generic function then
determines the class of the object and calls the respective method.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 25 / 49


Object-oriented programming in R: The S3 system

Example: Generics I

The print() function is probably the most famous generic function in R.


print

## function (x, ...)


## UseMethod("print")
## <bytecode: 0x0000000007a23488>
## <environment: namespace:base>

A generic’s body merely consists of calling the function UseMethod.


UseMethod first determines the class of x. Then, it’s looking for a method
suited for this class and calls it with x and .... If no appropriate function
exists, either a default method is called (if existing) or an error occurs.

base R offers individual print methods for most classes which display the
most important information respectively:

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 26 / 49


Object-oriented programming in R: The S3 system

Example: Generics II

x = factor(c("a", "a", "b"), x = table(sample(2, 50, replace = TRUE))


levels = c("a", "b")) str(x)
str(x)
## 'table' int [1:2(1d)] 28 22
## Factor w/ 2 levels "a","b": 1 1 2 ## - attr(*, "dimnames")=List of 1
## ..$ : chr [1:2] "1" "2"
print(x)
print(x)
## [1] a a b
## Levels: a b ##
## 1 2
class(x) = NULL ## 28 22
print(x)
class(x) = NULL
## [1] 1 1 2 print(x)
## attr(,"levels")
## [1] "a" "b" ##
## 1 2
## 28 22

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 27 / 49


Object-oriented programming in R: The S3 system

Methods
Each S3 method must be associated with a generic.
methods() lists all methods (from the search path) that belong to the
respective generic:
methods(cbind)
## [1] cbind.data.frame cbind.ts*
## see '?methods' for accessing help and source code

We’re recognizing a naming pattern: ’generic’.’class’(). This


pattern is mandatory; the generic is explicitly looking for methods
adhering to this naming pattern.
Thus, in this case the . is not only part of the name, but also part of
the OO definition. a.b means: Call method a of class b.
That’s why function names shouldn’t contain any periods unless they
are explicitly employing the S3 mechanics. Unfortunately, base R
doesn’t abide by this, e.g. the function t.test().
The default method follows the pattern ’generic’.default().
Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 28 / 49
Object-oriented programming in R: The S3 system

Implementing our own methods

To write our own print() method for our student class, it suffices to
define a function called print.student().
print.student = function(x) {
message = paste(x$Name, "is a good student.")
print(message)
}
print(stud)

## [1] "John Doe is a good student."

Caution: Our method must at least possess the same input parameters as
the generic function, e.g. since the generic print() function has an input
parameter x, our function print.student() must also possess an input
parameter x.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 29 / 49


Object-oriented programming in R: The S3 system

Implementing our own generics


We’ve already seen the contents of the generic print() function. To
create our own generic, we’re simply following this pattern:

print myGeneric = function (x, ...)


UseMethod("myGeneric")
## function (x, ...)
## UseMethod("print") myGeneric
## <bytecode: 0x0000000007a23488>
## <environment: namespace:base> ## function (x, ...)
## UseMethod("myGeneric")

Now, we can define our own (default) methods for this generic:

myGeneric.student = function(x) myGeneric.default = function(x)


return("This is myGeneric student.") return("It's a default")
myGeneric(stud) myGeneric(1:10)

## [1] "This is myGeneric student." ## [1] "It's a default"

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 30 / 49


Object-oriented programming in R: The S3 system

Inheritance in S3 I

S3 allows for the class attribute to have a length greater than 1. This is,
for example, utilized by the glm() function:
# Example from glm help:
counts <- c(18, 17, 15, 20, 10, 20, 25, 13, 12)
outcome <- gl(3,1,9)
treatment <- gl(3,3)
glmD93 <- glm(counts ~ outcome + treatment, family = poisson())
class(glmD93)

## [1] "glm" "lm"

Inheritance principle: Inside the vector, the specialized class comes


before the general class and it can define special behavior. If it
doesn’t, the behavior of the general class is used.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 31 / 49


Object-oriented programming in R: The S3 system

Inheritance in S3 II

The generic function begins by searching a method for the first


element of the vector. If none is found, it continues searching for the
second element and so on until the default is used.
We can use this to model the special behavior of our bachelor degree
students in statistics:

class(stud) = c("Bachelor Statistics Student", "Statistics Student", "Student")


str(attributes(stud))

## List of 2
## $ names: chr [1:4] "Name" "StudentID" "BeginningSemester" "Achievements"
## $ class: chr [1:3] "Bachelor Statistics Student" "Statistics Student" "Student"

As usually with S3: R doesn’t check on us. It’s our responsibility to ensure
that the ’Statistics Student’ is actually extending the ’Student’ and that,
for example, the getSemester() function can still be used.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 32 / 49


Object-oriented programming in R: The S3 system

Summary S3

Every R object can become an S3 object by adding the class attribute


to it.
There are no formal class definitions.
Methods don’t belong to objects, but to generic functions and are
denoted by a period inside their name.
Inheritance can be realized by assigning a vector of length greater than
1 to the class attribute.

S3 is a most minimal OO system: It’s not possible to remove a single


element and still have a functional OO system. In particular, R doesn’t
check on us. It’s our own responsibility to correctly use the S3 system.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 33 / 49


Object-oriented programming in R: The S4 system

Object-oriented programming in R: The S4 system

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 34 / 49


Object-oriented programming in R: The S4 system

An introductory example to S4
Since version 1.0, S3 has been a component of R. At the end of 2001, a
second OO system was introduced with R version 1.4: S4. S4 extends S3, in
particular through formal class definitions. As an example, we’ll take a look
at the Wave class from the tuneR package:
library(tuneR)
Wobj = sine(440)
typeof(Wobj)

## [1] "S4"

str(Wobj)

## Formal class 'Wave' [package "tuneR"] with 6 slots


## ..@ left : num [1:44100] 0 0.0626 0.1251 0.187 0.2481 ...
## ..@ right : num(0)
## ..@ stereo : logi FALSE
## ..@ samp.rate: num 44100
## ..@ bit : num 32
## ..@ pcm : logi FALSE

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 35 / 49


Object-oriented programming in R: The S4 system

Objects in S4

Immediately, we’re noticing differences and similarities:


The type of an S4 object is: S4. While we could use any data type for
S3, S4 is associated with a dedicated data type. It’s possible to check
for this data type using isS4().
The slots of S4 objects can be accessed using @ which replaces the $
operator that we know from lists.
Wobj@stereo
## [1] FALSE
Wobj@stereo <- TRUE

S4 objects don’t contain any methods, but merely properties. Thus,


just like S3, S4 follows the principle of generics as well.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 36 / 49


Object-oriented programming in R: The S4 system

Defining a class in S4
In S4, new classes can be defined by using the function setClass(). Apart
from the class name, this function also requires a list defining the
respective properties (in S4: slots). This list must be named and must
assign an already existing class to each property.
student = setClass(Class = "Student", slots = list(
Name = "character",
StudentID = "integer",
BeginningSemester = "POSIXct",
Achievements = "data.frame")
)
student

## class generator function for class "Student" from package '.GlobalEnv'


## function (...)
## new("Student", ...)

Out of the remaining arguments of setClass() only contains should still


be used. The other arguments are now deprecated and have been replaced
by better alternatives.
Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 37 / 49
Object-oriented programming in R: The S4 system

Creating new objects


New S4 objects can be created in two ways:
Using the function new(Class = class).
Through the return value of setClass(). This return value is a
function that calls new() with the respective class.

stud = student(Name = "John Doe", StudentID = 123456L,


BeginningSemester = ISOdate(2013, 10, 1))
str(stud)

## Formal class 'Student' [package ".GlobalEnv"] with 4 slots


## ..@ Name : chr "John Doe"
## ..@ StudentID : int 123456
## ..@ BeginningSemester: POSIXct[1:1], format: "2013-10-01 12:00:00"
## ..@ Achievements :'data.frame': 0 obs. of 0 variables
## Formal class 'data.frame' [package "methods"] with 4 slots
## .. .. ..@ .Data : list()
## .. .. ..@ names : chr(0)
## .. .. ..@ row.names: int(0)
## .. .. ..@ .S3Class : chr "data.frame"

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 38 / 49


Object-oriented programming in R: The S4 system

Methods in S4

To define a new method in S4, we can use setMethod():


fun = function(x) {
message = paste(x@Name, "is a good student.")
print(message)
}
setMethod("print",
signature = c(x = "Student"),
definition = fun
)

S4 automatically creates a generic print() function beforehand.


print(stud)

## [1] "John Doe is a good student."

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 39 / 49


Object-oriented programming in R: The S4 system

Generics in S4
Just like in S3, we can also define our own generics in S4. To this end, S4
offers the setGeneric() function:
setGeneric("myGeneric", def = function(x, y) print("This is a default"))

In our method, we’re now requesting two arguments of specific classes:


fun = function(x, y) {
if (y) print("Success") else print("Failure")
}
setMethod("myGeneric",
signature = c(x = "Student", y = "logical"),
definition = fun
)

Only when both have the required class, the call occurs:

myGeneric(stud, TRUE) myGeneric(stud, FALSE) myGeneric(stud, 5)

## [1] "Success" ## [1] "Failure" ## [1] "This is a default"

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 40 / 49


Object-oriented programming in R: The S4 system

Constructors with default values


We can write an initialize() method for default values which is directly
called upon calling new():

Since the generic initialize() new("Student")


possesses the formal argument
## An object of class "Student"
.Object, we also have to use it. ## Slot "Name":
## [1] "Dennis Default"
setMethod("initialize", ##
signature = c(.Object = "Student"), ## Slot "StudentID":
definition = function(.Object) { ## [1] 0
.Object@Name = "Dennis Default" ##
.Object@StudentID = 0L ## Slot "BeginningSemester":
.Object@BeginningSemester = Sys.time()## [1] "2022-03-24 10:41:50 CET"
return(.Object) ##
}) ## Slot "Achievements":
## data frame with 0 columns and 0 rows
The period is supposed to prevent
conflicts with other arguments.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 41 / 49


Object-oriented programming in R: The S4 system

Inheritance in S4
Inheritance structures can be specified in the class definition through the
contains argument.

The character vector contains new("B.Sc. Student")


specifies from which other S4
## An object of class "B.Sc. Student"
classes the new class shall inherit. ## Slot "Abschluss":
The new class automatically inherits ## character(0)
##
all slots from the old classes. ## Slot "Name":
## [1] "Dennis Default"
##
setClass(Class = "B.Sc. Student", ## Slot "StudentID":
contains = "Student", ## [1] 0
slots = list( ##
Abschluss = "character" ## Slot "BeginningSemester":
) ## [1] "2022-03-24 10:41:50 CET"
) ##
## Slot "Achievements":
## data frame with 0 columns and 0 rows

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 42 / 49


Object-oriented programming in R: The RC system

Object-oriented programming in R: The RC system

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 43 / 49


Object-oriented programming in R: The RC system

Reference classes

Since R Version 2.12 (October 2010), another OO system has been


supported, the so-called reference classes (RC). RC is very similar to S4,
but extends it in two central places:
RC doesn’t follow the principle of generics. Instead, methods are also a
part of objects.
Just like environments, RC follows the call-by-reference principle. In
fact, RC is a S4 class containing an environment.
StudentRC <- setRefClass("StudentRC")
typeof(StudentRC$new())
## [1] "S4"

Thus, RC much more resembles the OO system that is offered by other


programming languages like Java.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 44 / 49


Object-oriented programming in R: The RC system

Class definition

Classes are defined similarly to S4; in this case using setRefClass().


Properties belong to the fields argument and classes to inherit from to
the contains argument. What’s new: the methods argument for methods.
StudentRC <- setRefClass(Class = "StudentRC",
fields = list(
Name = "character",
StudentID = "integer",
BeginningSemester = "character",
Achievements = "data.frame"),
methods = list(
changeName = function(x) {
Name <<- x
}
)
)

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 45 / 49


Object-oriented programming in R: The RC system

RC objects
Just like for S4 objects, new() can be used to create an RC object.
stud = new("StudentRC", Name = "John Doe")

It’s good style to use the equivalent function of the class object:
stud = StudentRC$new(Name = "John Doe")

Individual fields can be accessed using the $ operator:


stud$Name

## [1] "John Doe"

The $ operator can also be used to access methods.


stud$changeName("Chantal Changename")
stud$Name

## [1] "Chantal Changename"

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 46 / 49


Object-oriented programming in R: The RC system

Call-by-Reference

Modifications to copied objects also take place inside the original object:

stud2 = stud stud$Name


stud2$changeName("Doris Double Change")
stud2$Name ## [1] "Doris Double Change"

## [1] "Doris Double Change"

To actually copy an object, copy() must be used.

stud2 = stud$copy() stud$Name


stud2$changeName("Tim Triple Change")
stud2$Name ## [1] "Doris Double Change"

## [1] "Tim Triple Change"

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 47 / 49


Conclusion

Conclusion

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 48 / 49


Conclusion

Conclusion

We have learned about the three OO systems in R: S3, S4 and RC.


S3 is sufficient for most cases: It’s easy to use and its minimalism is
noteworthy. It may be peculiar at times, but it does its job as long as
we’re following some simple rules.
S4 introduces many formalisms and thus gains some safeties which,
however, are usually not required.
RC implements a call-by-reference system. Being the most recent
system, it hasn’t fully matured yet and is still unknown to many.
Our recommendation: Use S3 and force yourselves to follow as many OO
guidelines as possible: Write and use constructors, getters and setters, etc.

Daniel Horn & Sheila Görz Advanced R Summer Semester 2022 49 / 49

You might also like