The Big R-Book. Philippe J. S. De Brouwer
Чтение книги онлайн.
Читать онлайн книгу The Big R-Book - Philippe J. S. De Brouwer страница 48
![The Big R-Book - Philippe J. S. De Brouwer The Big R-Book - Philippe J. S. De Brouwer](/cover_pre848614.jpg)
While the methods
package is always available when running R interactively (like in RStudio or in the R terminal), it is not necessarily loaded when running R in batch mode. So, you might want to include an explicit library(methods)
statement in your code when using S4.
6.3.1 Creating S4 Objects
While an S3 object can be used without defining it first, to create a valid S4 object, we need at least:
Name: An alpha-numeric string that identifies the class
Representation: A list of slots (or attributes), giving their names and classes. For example, a person class might be represented by a character name and a numeric age, as follows: representation(name = “character”, age = “numeric”)
Inheritance: A character vector of classes that it inherits from, or in S4 terminology, contains. Note that S4 supports multiple inheritance, but this should be used with extreme caution as it makes method lookup extremely complicated.
S4 objects are created with the function setClass()
.
setClass()
# Create the object type Acc to hold bank-accounts: setClass(“Acc”, representation(holder = “character”, branch = “character”, opening_date = “Date”)) # Create the object type Bnk (bank): setClass(“Bnk”, representation(name = “character”, phone = “numeric”)) # Define current account as a child of Acc: setClass(“CurrAcc”, representation(interest_rate = “numeric”, balance = “numeric”), contains = “Acc”) # Define investment account as a child of Acc setClass(“InvAcc”, representation(custodian = “Bnk”), contains = “Acc”)
This will only create the definition of the objects. So, to create a variable in your code that can be used to put your data or models inside, instances have to be created with the function new()
.
new()
Note the difference in syntax – for the function setClass
– between how the argument representation
and the argument contains
take values. The representation
cand we can create a firstode> argument takes a function and hence, more arguments can be passed by adding them comma separated. In order to passmore than one parent class to contains
, one needs to provide a character vector (for example c(“InvAcc”,“Acc”)
).
Both the arguments slots
and contains
will readily use S4 classes and the implicit class of a base type. In order to use S3 classes, one needs first to register them with setOldClass()
. If we do not want type control when an instance of a class is generated, we can provide to the slots
argument a special class “ANY” (this tell R not to restrict the input).
You might not have noticed right away, but we started off with a complex problem where some objects depend on others (in OO we speak about “parents” and “children”) and even where some objects take others as attributes. Those two things are very different and a little tricky to understand.
At this point, the classes Bnk
and Acc
exist and we can create a first instance for both.
# Create an instance of Bnk: my_cust_bank <- new(“Bnk”, name = “HSBC”, phone = 123456789) # Create an instance of Acc: my_acc <- new(“Acc”, holder = “Philippe”, branch = “BXL12”, opening_date = as.Date(“2018-10-02”))
6.3.2 Using S4 Objects
Now, we have two S4 objects and we can use them in our code as necessary. For example, we can change the phone number.
# Check if it is really an S4 object: isS4(my_cust_bank) ## [1] TRUE # Change the phone number and check: my_cust_bank@phone = 987654321 # change the phone number print(my_cust_bank@phone) # check if it changed ## [1] 987654321
In order to access slots of an S4 object, we use @
, not $
:
There is also a specific function to get attributes froman object: attr()
. This function allows to create attributes, change them or even remove them (by setting them to NULL)
attr()
# This will do the same as my_cust_bank@phone: attr(my_cust_bank, ‘phone’) ## [1] 987654321 # The function also allows partial matching: attr(my_cust_bank, which=’ph’, exact = FALSE) ## [1] 987654321 # attr can also change the value of an attribute. attr(my_cust_bank, which=’phone’) <- ‘123123123’ # Let us verify: my_cust_bank@phone ## [1] “123123123” # It is even possible to create a new attribute or remove one. attr(my_cust_bank, ‘something’) <- ‘Philippe’ attr(my_cust_bank, ‘something’) ## [1] “Philippe” attr(my_cust_bank, ‘something’) <- NULL attr(my_cust_bank, ‘something’) ## NULL str(my_cust_bank) # the something attribute is totally gone ## Formal class ‘Bnk’ [package “.GlobalEnv”] with 2 slots ## ..@ name : chr “HSBC” ## ..@ phone: chr “123123123”
While the function attr()
allows partial matching. It is never a good idea to use partial matching in a batch environment. This can lead to hard to detect programming errors.
Some slots – like class
, comment
, dim
, dimnames
, names
, row.names
and tsp
(for time series objects) – are special: they can only take some values. This knowledge can even be used to change those attributes.
x <- 1:9 x # x is a vector ## [1] 1 2 3 4 5 6 7 8 9 class(x) ## [1] “integer” attr(x, “dim”) <- c(3,3) x # is is now a matrix! ## [,1] [,2] [,3] ## [1,] 1 4 7 ## [2,] 2 5 8 ## [3,] 3 6 9 class(x) # but R is not fooled. ## [1] “matrix”