Читать книгу The Big R-Book - Philippe J. S. De Brouwer - Страница 186
♣6♣ The Implementation of OO
ОглавлениеR is an object oriented (OO) language but if you know how objects work in for example C++, it might take some mental flexibility to get your mind around how it works in R. R is not a compiled language, and it is build with versatility in mind. In some sense most objects are a to be considered as an object and can readily be extended without much formalism and without recompiling.1
OO
object oriented
Personally, I find it useful to think of R as a functional language with odd object possibilities. This means that if you want to make some simple analysis, then you might skip this section. We did our best to keep the knowledge of OO to a minimum for the whole book.
Programming languages that provide support for object oriented programming, allow code to be data-centric as opposed to functional languages that are in essence logic-oriented. They do that by introducing the concept of a “class.” A manifestation of that class then becomes the object that we can work with. Objects represent real life things. For example, if we want to create a software that manages bank accounts, it might be possible to have one object that is the account, another that is the customer, etc.
The main idea is that in other parts of the code we can work with the object “account” and ask that object for its balance. This has multiple advantages. First, of all, the logic of the way a balance is found is only in one place and in every call the same. Second, it becomes easier to pass on information and keep code lean: if you will need the balance all you have to do is import the object account and you inherit all its functionality.
There are other ways to keep code clean, for example creating an object, that is a savings account, will automatically inherit the functionality and data that all accounts share. So it becomes easy to create other types of accounts that are based on one primordial object account. For example, current accounts, savings accounts and investment accounts can all inherit from the object “account.” One of the basic things that all accounts will share is for example the way ownership works and how transactions are allowed. This can be programmed once and used in all types of accounts that inherit from this one. If necessary, this can even be overwritten, if there one type of account that uses another logic.
Another example could be how we can keep meta-data together with data.
The following code creates, for example, an attribute data_source
within the object df
.
L <- list(matrix(1:16, nrow=4)) L$data_source <- “mainframe 1” L$get_data_src <- function(){L$data_source} print(L$get_data_src()) ## [1] “mainframe 1”
In many ways, the list object (and many other objects) act as manifestations of objects that can freely be expanded. So already in the Section 4.3.6 “Lists” on page 41, we have used the object oriented capabilities of R explicitely. This might be a little bewildering and leaves the reader probably wondering what is the true object model behind R. Well, the answer is that there is not one but rather four types of classes.
Multiple OO systems ready to use in R. R's OO systems differ in how classes and methods are defined:
1 Base types. This is not a true OO system as it misses critical features like inheritance and flexibility. However, this underlies all other OO systems, and hence, it is worth to understand them a little. They are typically thought of as a struct in C.C
2 S3. S3 is a popular class type in R. It is very different from the OO implementation that is in most programming languages such as C++, C#, PHP, Java, etc. In those languages one would expect to pass a message to an object (for example ask the object my_account its balance as via the method my_curr_acc.balance(). The object my_account is of the type account and hence it is the logic that sits there that will determine what function balance() is used. These implementations are called message-passing systems., S3 uses a different logic: it is a generic-function implementation of the OO logic. The S3 object can still have its own methods, but there are generic functions that will decide which method to use. For example, the function print() will do different things for a linear model, a dataset, or a scalar.
3 Then there is also S4, which works very similarly to S3, but there is a formal declaration of the object (its definition) and it has special helper functions for defining generics and methods. S4 also allows for “multiple dispatch,” which means that generic functions can pick methods based on the class of any number of arguments, not just one.
4 Reference classes (RC) are probably closest to what you would expect based on your C++ or C# experience. RC implements a message-passing OO system in R. This means that a method (function) will belong to a class, and it is not a generic method that will decide how it behaves on different classes. The RC implementation uses the $. This means that a call to the function balance of an object of class account will look like my_account$dbalance(). RC objects in R are “mutable.” This means that they don't follow R's general logic “copy-on-modify” semantics, but are modified in place. This allows for difficult to read code but is invaluable to solve problems that cannot be solved in S3 or S4.
C++
C#
RC – reference class