Senger CodeLab πŸš€

How to properly document S4 class slots using Roxygen2

September 29, 2026

πŸ“‚ Categories: Programming
How to properly document S4 class slots using Roxygen2

Clear and comprehensive documentation is the bedrock of maintainable and reusable R code, especially when working with S4 classes. S4 classes, with their formal structure and slot definitions, offer powerful object-oriented programming capabilities in R. However, their complexity necessitates meticulous documentation using Roxygen2, a popular documentation generator for R packages. Mastering Roxygen2 for S4 slot documentation is crucial for collaborative projects and ensures your future self will thank you. This post dives into the best practices for documenting S4 class slots using Roxygen2, empowering you to write clear, concise, and informative documentation that enhances code usability and understanding.

Understanding S4 Classes and Slots

S4 classes provide a formal framework for object-oriented programming in R. They define objects with specific “slots,” which hold data. Think of slots as named containers for the various data elements that constitute your object. Unlike S3 classes, S4 classes enforce stricter type checking, ensuring data integrity and facilitating more robust code. Understanding this structure is fundamental to documenting them effectively.

For example, an S4 class representing a “book” might have slots for “title,” “author,” and “ISBN.” Each slot would hold a specific data type, like character strings for “title” and “author,” and a numeric value for “ISBN.”

This structured approach necessitates clear documentation to specify the purpose and expected data type of each slot, which is where Roxygen2 comes into play.

Leveraging Roxygen2 for S4 Slot Documentation

Roxygen2 simplifies the process of creating documentation for R packages. It uses specially formatted comments within your R code to generate help files automatically. For S4 classes, Roxygen2 offers specific tags to document slots effectively. The key is to use the @slot tag within your class definition.

Here’s the basic structure:

' @slot slotName Description of the slot. Data type expected in this slot. 

This simple yet powerful syntax clearly links the slot name with its description and expected data type. This makes your code easier to understand and use, both for others and your future self.

Best Practices for Documenting S4 Slots

While the @slot tag provides the basic functionality, incorporating some best practices can significantly enhance your documentation. Be explicit about the expected data type (e.g., character, numeric, logical). This helps prevent errors and ensures data integrity. For complex data structures within a slot, consider using @param for individual elements within the slot. This allows for granular documentation and clarity.

Provide concise yet comprehensive descriptions. Explain the purpose of the slot and how it relates to the overall class. Avoid jargon and use clear, straightforward language. For complex scenarios, illustrate with examples. A well-placed example can clarify complex concepts and demonstrate practical usage.

Consistently applying these practices ensures your documentation remains clear, concise, and informative, facilitating code reusability and maintainability.

Example: Documenting a Book Class

Let’s illustrate with a practical example. Consider the “Book” class mentioned earlier. Here’s how you would document its slots using Roxygen2:

' An S4 class to represent a book. ' ' @slot title Character. The title of the book. ' @slot author Character. The author of the book. ' @slot ISBN Numeric. The International Standard Book Number. setClass("Book", slots = list(title = "character", author = "character", ISBN = "numeric")) 

This example demonstrates the use of @slot to document each slot with its name, description, and expected data type. This concise documentation immediately clarifies the purpose and structure of the Book class.

For a more complex example, imagine a slot containing a list of chapters. Using @param for each element within the list would provide more detailed documentation.

  • Use @slot for every slot in your S4 class.
  • Be explicit about expected data types.
  1. Define the S4 class.
  2. Add Roxygen2 comments above the class definition.
  3. Use @slot to document each slot.

Infographic Placeholder: Visual representation of S4 class structure and Roxygen2 documentation.

Frequently Asked Questions

Q: What’s the difference between S3 and S4 classes in R?

A: S4 classes are more formal and structured than S3 classes. They offer stricter type checking and more powerful object-oriented features, but come with a slightly steeper learning curve. S3 classes are simpler and more flexible, but less rigorous in terms of type checking.

Properly documenting your S4 classes with Roxygen2 is an investment in code maintainability, reusability, and collaboration. By following these best practices and using the examples provided, you can significantly improve the quality of your R package documentation, making it easier for others (and your future self) to understand and utilize your code. Learn more about Roxygen2 here. Explore additional resources like Hadley Wickham’s Advanced R (https://adv-r.hadley.nz) and the official Roxygen2 vignette (https://cran.r-project.org/web/packages/roxygen2/vignettes/roxygen2.html) to further enhance your understanding. Start documenting your S4 classes effectively today and experience the benefits of well-documented code. Remember, good documentation is a sign of quality code.

Question & Answer :
For documenting classes with roxygen(2), specifying a title and description/details appears to be the same as for functions, methods, data, etc. However, slots and inheritance are their own sort of animal. What is the best practice – current or planned – for documenting S4 classes in roxygen2?

Due Diligence:

I found mention of an @slot tag in early descriptions of roxygen. A 2008 R-forge mailing list post seems to indicate that this is dead, and there is no support for @slot in roxygen:

Is this true of roxygen2? The previously-mentioned post suggests a user should instead make their own itemized list with LaTeX markup. E.g. a new S4 class that extends the "character" class would be coded and documented like this:

#' The title for my S4 class that extends \code{"character"} class. #' #' Some details about this class and my plans for it in the body. #' #' \describe{ #' \item{myslot1}{A logical keeping track of something.} #' #' \item{myslot2}{An integer specifying something else.} #' #' \item{myslot3}{A data.frame holding some data.} #' } #' @name mynewclass-class #' @rdname mynewclass-class #' @exportClass mynewclass setClass("mynewclass", representation(myslot1="logical", myslot2="integer", myslot3="data.frame"), contains = "character" ) 

However, although this works, this \describe , \item approach for documenting the slots seems inconsistent with the rest of roxygen(2), in that there are no @-delimited tags and slots could go undocumented with no objection from roxygenize(). It also says nothing about a consistent way to document inheritance of the class being defined. I imagine dependency still generally works fine (if a particular slot requires a non-base class from another package) using the @import tag.

So, to summarize, what is the current best-practice for roxygen(2) slots?

There seem to be three options to consider at the moment:

  • A – Itemized list (as example above).
  • B – @slot … but with extra tags/implementation I missed. I was unable to get @slot to work with roxygen / roxygen2 in versions where it was included as a replacement for the itemized list in the example above. Again, the example above does work with roxygen(2).
  • C – Some alternative tag for specifying slots, like @param, that would accomplish the same thing.

I’m borrowing/extending this question from a post I made to the roxygen2 development page on github.

Updated answer for Roxygen2 5.0.1, current as of 7.2.0

For S4, the best practice now is documenting using the @slot tag:

#' The title for my S4 class that extends \code{"character"} class. #' #' Some details about this class and my plans for it in the body. #' #' @slot myslot1 A logical keeping track of something. #' @slot myslot2 An integer specifying something else. #' @slot myslot3 A data.frame holding some data. #' #' @name mynewclass-class #' @rdname mynewclass-class #' @export 

On a sidenote, @exportClass is only necessary in some cases, the general way to export a function is using @export now. You also don’t have to export a class, unless you want other packages to be able to extend the class.

See also http://r-pkgs.had.co.nz/namespace.html#exports

Updated answer for Roygen2 3.0.0, current as of 5.0.1.

For S4, the best practice is documentation in the form:

#' \section{Slots}{ #' \describe{ #' \item{\code{a}:}{Object of class \code{"numeric"}.} #' \item{\code{b}:}{Object of class \code{"character"}.} #' } #' } 

This is consistent with the internal representation of slots as a list inside the object. As you point out, this syntax is different than other lines, and we may hope for a more robust solution in the future that incorporates knowledge of inheritance – but today that does not exist.

As pointed out by @Brian Diggs, this feature was pulled into 3.0.0, further discussion at https://github.com/klutometis/roxygen/pull/85