Introducing Another Object Orientation System

By Sebastian Warnholz, 0 comments.

This article is archived because of a reason. The content can be outdated or in draft form. You are welcome to read it anyway.

This is the second of a series of posts related to object oriented programming in R and the package aoos. The previous introduced the first version of aoos; this introduces version 0.2.0. the next is on different representations of reference classes in R.

R has more than enough systems for object orientation and here is yet another one. S3 and S4 are the built in systems. R.oo has been developed since 2001; proto since 2005; and R6 is the newest and published to CRAN in 2014.

What I wanted to have is a system where method definitions are part of the class definition. Something which forces me to define functions belonging to one concept in one place, however, I don’t feel comfortable to define them inside lists. So here I present my solution for your consideration.

As an example for this post consider the class Directory. defineClass is used to define a new class. If you want a field or method to be private, i.e. not easily accessible from the client, you can use the function ` private`. The class definition is a R-expression; every assignment in that expression will define a field or method.

## Downloading GitHub repo wahani/aoos@v0.2.0
## Installing aoos
## '/usr/lib/R/bin/R' --no-site-file --no-environ --no-save --no-restore  \
##   CMD INSTALL '/tmp/RtmpqT9OpB/devtools55174eeaa43/wahani-aoos-25d66d4'  \
##   --library='/usr/local/lib/R/site-library' --install-tests
## 
library("aoos")
## Loading required package: methods
Directory <- defineClass("Directory", contains = c("Show", "Binary"), {

  dirName <- private(getwd())

  init <- function(name) {
    if(!missing(name)) {
      if(!file.exists(name)) {
        message("Creating new directory '", name, "' ...")
        dir.create(name)
        }
       self$dirName <- name
    }
  }

  remove <- function(...) {
    filesInDir <- list.files(path = dirName, ...)
    if(length(filesInDir)) self - filesInDir else message("No files in directory!")
    invisible(self)
  }

  show <- function(object) {
    print(file.info(dir(dirName, full.names = TRUE))[c("size", "mtime")])
    }

  "./" <- function(e2) paste(dirName, "/", e2, sep = "")

  ".-" <- function(e2) file.remove(self/e2)

})

The class Directory is basically a S4 class and inherits from environment. You can only access public member; and the return value of defineClass is the constructor function, so you can use Directory() to create an instance of Directory. Arguments to the constructor are passed on to the init method if you have defined one. The class inherits from Show which means that the member function show is used as show-method, and Binary allows to define binary operators. On initialization a directory is created if it doesn’t exist. We start with a directory named ‘foo’.

foo <- Directory("foo")
## Creating new directory 'foo' ...
# Adding some data:
write.table(matrix(0, 10, 10), file = foo/"someData.txt")
write.table(matrix(0, 10, 10), file = foo/"someMoreData.txt")

# See whats inside 'foo':
foo
##                      size               mtime
## foo/someData.txt      292 2016-01-21 16:00:24
## foo/someMoreData.txt  292 2016-01-21 16:00:24
# One file would have been enough!
foo - "someMoreData.txt"
## [1] TRUE
# Check if it works:
foo
##                  size               mtime
## foo/someData.txt  292 2016-01-21 16:00:24
# Anyway, this is stupid:
foo$remove()
foo
## [1] size  mtime
## <0 rows> (or 0-length row.names)
## [1] TRUE

If you are still interested you can install the package from Github or CRAN.