When dealing with a programming task pertaining to a specific business domain, developing custom objects with their related methods can enhance your work quality and usability.
Consider, for instance, a programmer dealing with a logistics project. Imagine him facing a choice of different types of means of transport packed with different attributes, cost functions, and time availability.
Defining different classes for these means of transport and adding proper attributes and methods to these classes will let you build a specific domain language that is able to represent, in a convenient way, the real problem you are trying to solve with your code. This concept is further explained in The Pragmatic Programmer by Andrew Hunt and David Thomas.
R comes packed with three different systems for object-oriented programming, which are as follows:
In the following example, we are going to use the S3 system, define a custom truck class, add attributes, and a proper method to change the date of last maintenance.
truck
class with custom attributes:trucks <- function(plate = "XXNNNZZ", night_trips = TRUE, kilometers = 0, last_maintenance = "00/00/1900" ) { me <- structure(list( night_trips = night_trips, kilometers = kilometers, last_maintenance = last_maintenance ), class= "trucks") return(me) }
volvo
truck specifying the plate, kilometers, and date of last maintenance:volvo <- trucks(plate = "BE705WT",kilometers = 2000,last_maintenance = "17/01/2013")Add a method to set maintenance date after first initialization set_last_maintenance <- function(entity,value_to_set) { UseMethod("set_last_maintenance",entity) } set_last_maintenance.default <- function(entity,value_to_set) { return(NULL) } set_last_maintenance.trucks <- function(entity,value_to_set) { entity$last_maintenance <- value_to_set message("maintenance date was set correctly") return(entity) }
volvo <- set_last_maintenance(volvo,"10/01/2016")Check results volvo$last_maintenance
In step 1, we create the truck
class with custom attributes. In the first step, new classes are declared with a function-like syntax, where the default values for class attributes are passed as arguments. In the body of the function, an inner reference is made using the pronoun me
in order to refer to the function itself.
Using this terminology, the class attributes and names are declared. Finally, with the return(me)
statement, the new truck
class is returned as a value for the function.
At the end of this procedure, a new trucks
function will be stored in your environment, as made clear by the RStudio environment explorer:
In step 2, we create a Volvo truck, specifying the plate, kilometers, and date of last maintenance. This step simply involves calling the trucks()
function and assigning a function value to the volvo
object.
Once again, the RStudio environment explorer clearly shows the class attribute for the newly arrived volvo
entity:
In step 3 we add a method to set a maintenance date after first initialization. The third step basically involves three activities, which are as follows:
set_last_maintenance
function.truck
.trucks
class. In this last step, we tell the function what to do with the trucks object being passed to it.Particularly, with the entity$last_maintenance <- value_to_set
statement, we tell the function to change the last_maintenance
attribute to a value that was passed to the function.
The final statement return(entity)
is very important. The lack of this causes the changes made in this function to have no effect on the outside environment.