K32 Oop
K32 Oop
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
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.
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 ... ... ... ...
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
The ideas behind a class and an object might seem familiar to us. After all,
they correspond to some statistical terms:
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.
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")
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.
Inheritance I
Inheritance II
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.
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
Objects in R
S3 objects
names(attributes(iris)) names(attributes(table(iris$Species)))
Class definitions in S3 I
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
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()
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"
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.
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.
Example: Generics I
base R offers individual print methods for most classes which display the
most important information respectively:
Example: Generics II
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
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)
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.
Now, we can define our own (default) methods for this generic:
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)
Inheritance in S3 II
## 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.
Summary S3
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)
Objects in S4
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
Methods in S4
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"))
Only when both have the required class, the call occurs:
Inheritance in S4
Inheritance structures can be specified in the class definition through the
contains argument.
Reference classes
Class definition
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")
Call-by-Reference
Modifications to copied objects also take place inside the original object:
Conclusion
Conclusion