Читать книгу The Big R-Book - Philippe J. S. De Brouwer - Страница 219
6.3.7 Creating S4 Generics
ОглавлениеR provides specific tools functions to create new generics and methods:
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.
# debet # Generic function to debet an account # Arguments: # x -- account object # y -- numeric -- the amount to be taken from the account # Returns # confirmation of action or lack thereof debet <- function(x,y){useMethod()} # Make it a generic function that verifies the balance # before the account a debet is booked. setGeneric(“debet”) ## [1] “debet” # Add the debet() function as a method for objects of type CurrAcc setMethod(“debet”, c(“CurrAcc”), function (x, y) { if(x@balance >= y) { new_bal <- x@balance + y} else { stop(“Not enough balance.”) } new_bal } ) ## [1] “debet” # Test the construction: my_curr_acc@balance # for reference ## [1] 600 my_curr_acc@balance <-debet(my_curr_acc, 50) my_curr_acc@balance # the balance is changed ## [1] 650 # We do not have enough balance to debet 5000, so the # following should fail: my_curr_acc@balance <-debet(my_curr_acc, 5000) ## Error in debet(my_curr_acc, 5000): Not enough balance. my_curr_acc@balance # the balance is indeed unchanged: ## [1] 650