The Big R-Book. Philippe J. S. De Brouwer

Чтение книги онлайн.

Читать онлайн книгу The Big R-Book - Philippe J. S. De Brouwer страница 51

The Big R-Book - Philippe J. S. De Brouwer

Скачать книгу

alt="image"/> Note – Nuances in the OO system

      The downside of the function centricOOsystem is that some things become a little subtle. Earlier we explained how to use isS4(). There is no function isS3(), but one will notice that is.S3() exists. Now, you will understand that is.S3() is the S3 specific method of the function is().

      Looking up the source code can be helpful:

      is.S3 ## function(x){is.object(x) & !isS4(x)} ## <bytecode: 0x5634256e9f60>

      There are many functions related to S4 objects, and it is not the aim to provide a full list however, the following might be useful for your code.

       getGenerics() lists all S4 generics;

       getGenerics()

       getClasses() lists all S4 classes (it does however, include shim classes for S3 classes and base types);

       getClasses()

       showMethods() shows the methods for one or more generic functions, possibly restricted to those involving specified classes. Note that the argument where can be used to restrict the search to the current environment by using where = search();

       showMethods()

      6.3.7 Creating S4 Generics

       setGeneric() creates a new generic or converts an existing function into a generic.

       setGeneric()

       setMethod() creates a method for a generic function aligned to a certain class. It takes as argument the function, the signature of the class and the function definition.

       setMethod()

      We will build further on the example of the bank accounts as used in the previous sections of this chapter. As a first step, we can create methods to credit and debit a current account S4 object.

      # setGeneric needs a function, so we need to create it first. # credit # Dispatcher function to credit the ledger of an object of # type ‘account’. # Arguments: # x -- account object # y -- numeric -- the amount to be credited credit <- function(x,y){useMethod()} # transform our function credit() to a generic one: setGeneric(“credit”) ## [1] “credit” # Add the credit function to the object CurrAcc setMethod(“credit”, c(“CurrAcc”), function (x, y) { new_bal <- x@balance + y new_bal } ) ## [1] “credit” # Test the function: my_curr_acc@balance ## [1] 500 my_curr_acc@balance <- credit(my_curr_acc, 100) my_curr_acc@balance ## [1] 600

      While the functionality for credit might seem trivial, in reality crediting an account will require a lot of checks (e.g. sanctioned countries and terrorist financing). So, let us create now a little more useful example with a function debet(), because before debiting an account, one will need to check if there is enough balance.

      image Warning – Overloading functions

      If you want to overload an existing function such as union() and exp(), then you should of course not define the function first – as in the first line in the aforementioned code. Doing so will make its original definition unavailable.

      6.3.8 Method Dispatch

      In its most simple form, S4 dispatching is similar to S3 dispatching. However, the implementation for S4 is more powerful. When an S4 generic function dispatches on a single class with a single parent, then S4 method dispatch is no different from the S3 method dispatch.

      For practical use, the main difference is how default values are defined. In S4, there is a special class “ANY” that functions as the default.

      Similarly to S3, S4 knows about group generics. Further, details can be found in the function documentation (visualize the documentation – as usual – with the command ?S4groupGeneric. There is also a function to call the “parent method”: callNextMethod().

       S4groupGeneric()

       callNextMethod()

      The main advantage of S4 is that it is possible to dispatch on multiple arguments (though it all becomes a little more complicated and abstract). That is the case when you have multiple parent classes. The rules can be found in the documentation of the function Methods.

       Methods()

      These aspects require utmost care. Personally, the author believes that this is where the S4 OO implementation stops to be practically relevant. When one needs further dependencies and complexity the S4 method becomes too easy too complex and it might be hard to predict which method will be called.

      Finally, there are methods that allow us to identify which method gets called,

Скачать книгу