-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path07-OO_Programming.Rmd
200 lines (130 loc) · 8.78 KB
/
07-OO_Programming.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# Object-Oriented Programming with R and Python
At this point we are ready to expand our exploration with object-oriented programming (OOP) in R and Python. Objects are like (collections of one or more) functions with some added structure. This structure has been defined by the four principles which set apart OOP.
* Abstarction \index{Abstraction}.
* Encapsulation \index{Encapsulation}.
* Inheritance \index{Inheritance}.
* Polymorphism \index{Polymorphism}.
Additionally the functions an object contains, called it's methods are conceptualized as relating to the actions of the object. The methods are actions which are done by the object for itself - an add method enables the object to add itself. A square object would add something to itself in an internally defined fashion.
Consider a function/method to transparently operates on a variable as would be appropriate to the data-type. This is **polymorphism**, a consequence of the message-passing \index{message-passing} model. An 'add' method would do some sort of add operation in a fashion appropriate to the object and the input, and it would do it by passing a "do add"" message into the blackbox of the object and the details are inaccessible to the user. Access to the objects characteristics is also by such methods and in no other way. This is **encapsulation** or 'information hiding'.
You can only alter an object itself by extending it's pattern in a new object. All the things of the old object are passed on and exist in the new object by re-inplementation of old characteristics and new characteristics and behaviors are implemented on top of the parent object's pattern. This is **inheritance**.
As above the object has control over how it is seen in the environment external to the object. The picture the object releases is an **abstraction** of it's pattern definition and contents. The totality of object data structure emerges from the outputs of the object methods.
A generic class pattern\index{class pattern} or definition (in pseudocode) consists of a class signature (or name) and a contained code block with class details. This is the fundamental abstraction which is an object. It could be represented like this,
```{}
# Class indentity
class() [ include inheritance]
#Class details
# the characteristics
class constants
class variables
# instance creation
constructor()
# class actions
methods()
```
## Defining Classes in R and Python
A class is a specific object pattern, The automobile class is an object with wheels, some mode of propulsion and driver methods. A class instance is a particular realization of car with specifics values added to characteristics inherited from the class.
**R, Functions or Classes**
Due to how it evolved, R has at least 3 kinds or levels of objects, developed in a chronologic order. These all, arguably, then strain the limits of what is or is not Object-Oriented. The explanation offered^22^ is the origin of R from S as an interactive environment and further development faces compromises to this. It can be used as a scripting language, even as if running programs but at the base of it all the interpreter runs the scripts in the the main over it's interactive nature.
I think in an important sense none of the OOP attempts fit the bill. Witness that there are 3 attempts to provide an R environment for Object-Oriented development and all have different shortcomings in the implementation. Add further what is actually a 4th object-oriented-type, but outside of core-R, with the [R6 Package](https://github.com/r-lib/R6/). Summarizing,
* \index{S3} (predominantly genertic functions without formal class definition)
* \index{S4} (Class definitions)
* RC (\index{Reference Class}es, or 'euphemistically' S5 or \index{R5})
* \index{R6} (External to Core-R R6 package)
The result of all this is that only the masochistically R obscessed or extreme programmer ventures here. R scripting afficionados even with lots of time proceed with caution.
I learned Object-Oriented Programming with Java and statistics with R. After a look further inside R for OOP, I decided I wasn't going there - all the more reason for adding Python to one's Data Science repertoir.
I am not going to explore R OOP \index{R OOP} beyond the discussion under calling R objects below, really *a syntatic variant* of functional programming. Those readers truly coming from R will understand. \index{syntax}
**Python Objects**
In contrast to R python Object-Oriented Programming meets nearly everybody's understanding of OOP. Python Objects \index{Python Objects} when instantiated look, feel and behave like an object for me. The python system of namespaces \index{namespace}s and variable visability blend consistently with the idea of encapsulation and data-hiding.
Python objects inherit from parent objects as expected and polymorphism operates behind the object envelope transparently and as one logicall expects for data-types or structures. Abstraction is a conceptualization of the data-structres created as objects.
Lets create a simple python class^8-p627^ like,
\index{syntax}
```{python}
# python code
class SimpleClass:
# Define the class object
# Note: Implied constructor is
# that of the base object of
# the python environment.
# Define class methods
def setdata(self, value): # a value 'setter' method
self.value = value # \index{self} is the instance itself
def getdata(self): # a value 'getter' method
print(self.value)
# create object instance from class definition
x = SimpleClass()
x.setdata(5) # x became '\index{self}' in the abstract
x.getdata() # what is the value of x
```
```{python}
print(x.value)
```
Well, now we just accessed the value of x directly - not hidden data as we should expect.
Let's try another, the ubiquitous Car example \index{Car example}.
\index{syntax}
```{python}
# what is a car?
class Car:
_motor = ""
_style = ""
_year = ""
def __init__(self, year, style, motor): # constructor, always an __init__ function
self._motor=motor
self._style=style
self._year=year
def setmotor(self, motor): # setters
self._motor=motor
def setstyle(self, style):
self._style=style
def getmotor(self): # getters
return _self.motor
def getstyle(self):
return _self.style
def toString(self):
return (self._year+","+self._motor+","+self._style)
# build a car
Newcar = Car('2019','Sedan', '4 cylinder gasoline' )
# What is 'our' Newcar?
print(Newcar)
```
OOoops I printed out the object info \index{object info vs instance data} not the instance data!
What happens if I try direct access to an instance variable 'style'?
```{}
print(Newcar.style)
```
We get an error,
```{}
Error in py_run_string_impl(code, local, convert) :
AttributeError: 'Car' object has no attribute 'style'
Detailed traceback:
File "<string>", line 1, in <module>
Calls: <Anonymous> ... py_capture_output -> force -> py_run_string -> py_run_string_impl
Execution halted
```
Unfortunately, it is still accessible but you need to use the internal name '_style'
```{python}
print(Newcar._style)
```
Well in terms of encapsulation in python OOP, close but no cigar. But as [leandrotk](https://medium.com/@leandrotk_) notes in [this blog](https://medium.com/the-renaissance-developer/python-101-object-oriented-programming-part-2-8e0db3ddd531) \index{Non-public variablesas convention}
> Non-public variables are just a convention and should be treated as a non-public part of the API.
That means when we see the leading underscore \index{leading underscore} weare 'pretending' the variable is private. The responsibility rests with the programmer. The only way to control it at all is to not document the underscore for the object's API.
Now try again using the object's own print method.
```{python}
print(Newcar.toString())
```
What about inheritance? Let's subclass the car as a truck.
```{python}
class Truck(Car):
_type = ""
def __init__(self, year, style, motor, type):
super().__init__(year, style, motor)
self._type = type
def toString(self):
return super().toString() + "," + self._type
Bigtruck = Truck('2018','Truck','6 cylinder diesel', 'box' )
print(Bigtruck.toString())
```
We have used the car pattern, referring to it as the superclass super. and we have overridden the tostring function to include the _type variable appended to the car string.
## Using Objects and Classes
An instance of a class is created by the class constructor \index{constructor}. An object constructor is implicitly inherited by all classes, from the language's object definition and implementation. It is often explicitly overridden by a customized contructor.
### R Scripting
### Python Scripting