S7 Object-Oriented Programming System for R

repository·main·Indexed 17 days ago

https://github.com/rconsortium/s7

S7 is an experimental object-oriented programming system for R designed as a successor to S3 and S4. It features formal class definitions via new_class(), property validation, and a functional OOP approach using generics created with new_generic() and methods registered via the method<- operator.

Tokens
887
Snippets
4
Records
5
Agent score
17%

What's inside S7

  1. Access and set object properties

    main

    Data stored within an S7 object is referred to as properties. You use the @ operator to both retrieve and assign property values.

    Properties are automatically validated against the types declared in new_class() and against the class's validator function upon assignment.

    x@start          # Get property
    x@end <- 20     # Set property
  2. Troubleshoot fr_schema validation errors

    main

    When working with the fr package (which utilizes S7 for object validation), you may encounter validation errors stating that an fr_schema object is invalid. The specific error message is:

    Error: <fr::fr_schema> object is invalid: - all items in @fields should be fr_field objects

    This indicates that the fields component of an fr_schema object contains elements that are not valid fr_field objects. This error commonly surfaces during:

    • Running examples (e.g., using as_data_frame() on an fr_tdr object).
    • Running tests (e.g., testthat failures).
    • Building vignettes (e.g., creating_a_tabular-data-resource.Rmd or read_fr_tdr.Rmd).
    • Executing code in vignettes using as_fr_tdr() or read_fr_tdr().
  3. Create generics and methods

    main

    S7 uses a functional OOP model where methods are associated with generic functions.

    1. Create a generic: Use new_generic() to define a new generic function. Use the := operator to name it. If the generic requires arguments that are not used for dispatch, provide a body via the fun argument.
    2. Define a method: Use the method<- assignment operator to register a specific implementation for a class.

    Methods can also be registered for base types on S7 generics, or for S7 classes on existing S3/S4 generics.

    # 1. Create the generic
    inside := new_generic("x")
    
    # 2. Define a method for a specific class
    method(inside, Range) <- function(x, y) {
      y >= x@start & y <= x@end
    }
    
    # 3. Call the generic
    inside(x, c(0, 5, 10, 15))
  4. Define S7 classes and objects

    main

    S7 classes are formally defined using new_class(). A class definition includes a list of properties (specifying types) and an optional validator function to ensure object integrity.

    To name the class, use the := operator during assignment. The object returned by new_class() serves as the constructor for creating instances of that class.

    Range := new_class(
      properties = list(
        start = class_double,
        end = class_double
      ),
      validator = function(self) {
        if (length(self@start) != 1) {
          "@start must be length 1"
        } else if (length(self@end) != 1) {
          "@end must be length 1"
        } else if (self@end < self@start) {
          "@end must be greater than or equal to @start"
        }
      }
    )
    
    # Create an instance
    x <- Range(start = 1, end = 10)