14.1 Introduction

This chapter describes the R6 OOP system. R6 has two special properties:

  • It uses the encapsulated OOP paradigm, which means that methods belong to objects, not generics, and you call them like object$method().

  • R6 objects are mutable, which means that they are modified in place, and hence have reference semantics.

If you’ve learned OOP in another programming language, it’s likely that R6 will feel very natural, and you’ll be inclined to prefer it over S3. Resist the temptation to follow the path of least resistance: in most cases R6 will lead you to non-idiomatic R code. We’ll come back to this theme in Section 16.3.

R6 is very similar to a base OOP system called reference classes, or RC for short. I describe why I teach R6 and not RC in Section 14.5.


  • Section 14.2 introduces R6::R6class(), the one function that you need to know to create R6 classes. You’ll learn about the constructor method, $new(), which allows you to create R6 objects, as well as other important methods like $initialize() and $print().

  • Section 14.3 discusses the access mechanisms of R6: private and active fields. Together, these allow you to hide data from the user, or expose private data for reading but not writing.

  • Section 14.4 explores the consequences of R6’s reference semantics. You’ll learn about the use of finalizers to automatically clean up any operations performed in the initializer, and a common gotcha if you use an R6 object as a field in another R6 object.

  • Section 14.5 describes why I cover R6, rather than the base RC system.


Because R6 is not built into base R, you’ll need to install and load the R6 package to use it:

# install.packages("R6")

R6 objects have reference semantics which means that they are modified in-place, not copied-on-modify. If you’re not familiar with these terms, brush up your vocab by reading Section 2.5.