--- title: "retListClasses" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{retListClasses} %\VignetteEngine{knitr::rmarkdown} %\usepackage[utf8]{inputenc} --- ## retList classes `retList` can be used as a shortcut to: ```{r eval=FALSE} constructor <- function(...) { ... out <- list(...) class(out) <- "constructor" out } ``` vs. ```{r eval=FALSE} constructor <- function(...) { ... retList("constructor") } ``` It will simply find all objects in the environment in which it is called and returns those in a list. This is one way to think about and implement features associated with object orientation in *R*. ## Basics Every value bound to a symbol will be public, objects with a leading dot in the name will be private. This can be changed by stating which names to make public explicitely. Here is a simple class definition: ```{r} library("aoos") Person <- function(name) { print <- function(x, ...) { cat(paste0("Hello, my name is ", .self$name, ".\n")) } retList(c("Person", "Print")) } ``` `retList` is used as a generic constructor function. It allways returns a list containing all visible values from the environment where it is called. There is a print method `print.Print` in the package which will look for a member function called print for printing. Thus the `print` method in the class *Person* will be used as *S3* printing method. ```{r} ann <- Person("Ann") ann ``` Inside the class definition - i.e. the body of the constructor - you can use `.self` but you do not have to; It just might be more explicit. You can also use the super-assignment operator `<<-`. Note that `.self` is not a reference to the instance itself, it is only referencing to the environment in which the methods will live in. You should keep in mind that a public field is a value in a list and not a reference to the value in `.self`. Thus, if your object should have public fields you have to define get/set methods. In this example you can think of `name` as an attribute since changing it in an instance won't change the bahavior of `greet`. Here is something you can do instead: ```{r} Person <- function(.name) { print <- function(x, ...) { cat(paste0("Hello, my name is ", .self$.name, ".\n")) } name <- function(x) { if (!missing(x)) .name <<- x .name } retList(c("Person", "Print")) } p <- Person("Ann") p p$name() p$name("Paul") p ``` Although I don't understand why 'Ann' can change to be 'Paul', this is one way of adding something like reference semantics. ## Inheritance An object can inherit from another object. The constructer then extends the instance of the super class/object. For that you can supply a call to the super classes constructor function, where you also have to supply arguments for initialization. ```{r} Person <- function(name) { print <- function(x, ...) { cat(paste0("Hello, my name is ", .self$name, ".\n")) } retList(c("Person", "Print")) } Employee <- function(id, ...) { print <- function(x, ...) { cat("Name: ", name, "\nID: ", id) } retList("Employee", super = Person(...)) } kalle <- Employee("1", "Kalle") str(kalle) kalle ```