-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclassesS4.Rmd
89 lines (66 loc) · 2.1 KB
/
classesS4.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
---
title: "classes - S4"
date: 2018-02-04T12:00:04+01:00
draft: false
image: "classes.jpg"
categories: ["R"]
tags: ["R", "OOP"]
---
## 1. Why would you use OOP in R?
Object oriented programming in R is unfortunately rather complicated comparing to Python (which seems to be the only reasonable alternative for data science programming).
However, there are certain cases when OOP may come up helpful:
* when you write your own package and you want users to work on an object that your function returns (print, summary, plot);
* learning OOP in R is a good investment, because it let's you understand better how functions like print, plot etc. work.
## 2. Creating a new class in S4
Let's define a new class:
```{r}
setClass(
Class = 'Polygon',
slots = c(x = 'numeric', y = 'numeric'),
)
```
where `Polygon` is it's name and `slots` are it's attributes.
A new instance of class `Polygon`:
```{r}
w1 <- new('Polygon', x = 1:3, y = c(1, 1, 2))
```
## 3. Attributes
If you've ever wondered what `@` in R means, here's the answer:
```{r}
slotNames(w1)
w1@x
w1@y
```
It provides access to inctance attributes. You can also overwrite current attributes simply with:
```{r}
w1@x <- c(3, 2, 1)
```
## 4. Methods
Let's create a simple method `show` which prints a description of our object.
```{r}
setMethod(
f = 'show',
signature = c(object = 'Polygon'),
function(object) {
cat(sprintf('This is a polygon with %d sides.\n', length(object@x)))
cat(sprintf('(%g, %g)', object@x, object@y))
cat('\n')
}
)
print(w1)
```
Yes, so far OOP in R looks extremely complicated and non-intuitive comparing to Python.
## 5. Inheritance
A simple example of inheritance:
```{r}
setClass(
'Triangle',
contains = 'Polygon',
validity = function(object)
if (length(object@x) != 3) "a triangle has three sides" else TRUE
)
t1 <- new('Triangle', x=c(1, 2, 3), y=c(1, 1, 3))
class(t1)
show(t1)
```
You can see that a new class `Trinagle` ingerits `x` and `y` attributes and `show` method from class `Polygon`. It also adds a validity check, which produces an error if the number of vertices is different than 3.