### Method Explanation Example Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-introspect.md This output shows all possible method combinations for a generic function, indicating which ones are applicable (marked with '*') and which are not. ```R add([foo2], [foo2]) -> add([foo2], [foo1]) add([foo2], [S7_object]) add([foo2], [ANY]) add([foo1], [foo2]) * add([foo1], [foo1]) add([foo1], [S7_object]) add([foo1], [ANY]) add([S7_object], [foo2]) add([S7_object], [foo1]) add([S7_object], [S7_object]) add([S7_object], [ANY]) add([ANY], [foo2]) add([ANY], [foo1]) add([ANY], [S7_object]) add([ANY], [ANY]) ``` -------------------------------- ### Install S7 package Source: https://github.com/rconsortium/s7/blob/main/README.md Install the S7 package from CRAN. ```r install.packages("S7") ``` -------------------------------- ### Reasonable Tracebacks for Dispatched Methods Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-dispatch.md Provides examples of how errors from dispatched methods result in reasonable tracebacks, showing the call stack. ```R my_generic(10) ``` ```R my_generic(3, 4) ``` -------------------------------- ### Get and Set Properties with prop() Source: https://context7.com/rconsortium/s7/llms.txt Use the `prop()` function to get and set properties. This provides an alternative to the `@` operator and allows for options like skipping validation. ```r Horse <- new_class("Horse", properties = list( name = class_character, colour = class_character, height = class_numeric )) lexington <- Horse(colour = "bay", height = 15, name = "Lex") # Get property with prop() prop(lexington, "colour") #> [1] "bay" # Set property with prop<- prop(lexington, "height") <- 15 lexington@height #> [1] 15 # Type validation on assignment try(lexington@height <- "tall") #> Error: @height must be , not # Skip validation with check = FALSE (use carefully) prop(lexington, "height", check = FALSE) <- 14 ``` -------------------------------- ### Define Multiple Dispatch Methods Source: https://context7.com/rconsortium/s7/llms.txt Set up multiple dispatch by defining methods for a generic with multiple arguments. This example defines `greet` for `Dog` and `Cat` with `English` and `French` languages. ```r Language <- new_class("Language") English <- new_class("English", Language) French <- new_class("French", Language) greet <- new_generic("greet", c("animal", "language")) method(greet, list(Dog, English)) <- function(animal, language) "Woof" method(greet, list(Dog, French)) <- function(animal, language) "Ouaf Ouaf" method(greet, list(Cat, English)) <- function(animal, language) "Meow" method(greet, list(Cat, French)) <- function(animal, language) "Miaou" greet(Dog(), French()) #> [1] "Ouaf Ouaf" ``` -------------------------------- ### Get All Properties with props() Source: https://context7.com/rconsortium/s7/llms.txt Retrieve all properties of an object at once using the `props()` function. This returns a named list of the object's properties. ```r Range <- new_class("Range", properties = list( start = class_double, end = class_double ), validator = function(self) { if (self@end < self@start) "@end must be >= @start" } ) r <- Range(start = 1, end = 10) # Get all properties props(r) #> $start #> [1] 1 #> #> $end #> [1] 10 ``` -------------------------------- ### Set properties with type constraints Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/property.md Examples of attempting to set properties with values of incorrect types, triggering errors based on the defined class constraints. ```R my_obj@null <- "x" ``` ```R my_obj@base <- "x" ``` ```R my_obj@S3 <- "x" ``` ```R my_obj@S4 <- "x" ``` ```R my_obj@S7 <- "x" ``` ```R my_obj@S7_union <- "x" ``` -------------------------------- ### Coerce to data frame example Source: https://github.com/rconsortium/s7/blob/main/revdep/problems.md Demonstrates coercing a 'fr_tdr' object into a data frame. This example failed due to an invalid 'fr_schema' object. ```r as_fr_tdr(mtcars, name = "mtcars") |> as_data_frame() ``` -------------------------------- ### Single Dispatch Failure Examples Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-dispatch.md Illustrates informative error messages when single dispatch fails to find a suitable method for the given argument type. ```R fail(TRUE) ``` ```R fail(tibble::tibble()) ``` ```R fail(foo()) ``` ```R fail(Foo(x = 1)) ``` -------------------------------- ### Multiple Dispatch Failure Examples Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-dispatch.md Shows informative error messages when multiple dispatch fails to find a suitable method for the combination of argument types. ```R fail(TRUE) ``` ```R fail(, TRUE) ``` ```R fail(TRUE, TRUE) ``` -------------------------------- ### Access and modify properties Source: https://github.com/rconsortium/s7/blob/main/README.md Use the @ operator to get or set object properties. ```r x@start x@end <- 20 x ``` -------------------------------- ### Validate property with custom validator Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/property.md Define and apply custom validators to properties. This example shows validation for property length and object property validity. ```R f <- foo(x = 1L) f@x <- 1:2 ``` ```R foo(x = 1:2) ``` -------------------------------- ### Validate new property default value Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/property.md The default value for a new property must be an instance of the specified class. This example shows an error when a character is provided for an integer default. ```R new_property(class_integer, default = "x") ``` -------------------------------- ### Inherited Validator in Abstract Classes Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/class.md Abstract classes can utilize inherited validators. The example shows `foo2` using a validator from its abstract parent class. ```R foo2(x = 2) ``` -------------------------------- ### Create properties list with validation Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/property.md Use `as_properties()` to create a list of properties, with built-in validation for list structure, naming, and class compatibility. ```R as_properties(1) ``` ```R as_properties(list(1)) ``` ```R as_properties(list(new_property(class_character))) ``` ```R as_properties(list(x = 1)) ``` ```R as_properties(list(x = class_character, x = class_character)) ``` -------------------------------- ### Register Methods with method<- Source: https://context7.com/rconsortium/s7/llms.txt Implement methods for specific classes on generic functions, supporting S7, S3, and S4 systems. ```r library(S7) # Define classes and generic Dog <- new_class("Dog", properties = list(name = class_character)) Cat <- new_class("Cat", properties = list(name = class_character)) speak <- new_generic("speak", "x") # Register methods for S7 classes method(speak, Dog) <- function(x) "Woof!" method(speak, Cat) <- function(x) "Meow!" # Use the generic speak(Dog(name = "Rex")) #> [1] "Woof!" speak(Cat(name = "Whiskers")) #> [1] "Meow!" ``` -------------------------------- ### Instantiate an S7 class Source: https://github.com/rconsortium/s7/blob/main/README.md Create an instance of the defined class using the class constructor. ```r x <- range(start = 1, end = 10) x ``` -------------------------------- ### Property Accessors API Source: https://context7.com/rconsortium/s7/llms.txt Provides mechanisms to get and set object properties using the @ operator or the prop() function, with built-in validation. ```APIDOC ## prop(object, name, check) ### Description Access or modify a specific property of an S7 object. The @ operator is the standard shorthand for this functionality. ### Parameters - **object** (S7 object) - Required - The object to access. - **name** (string) - Required - The name of the property. - **check** (boolean) - Optional - Whether to perform type validation (default: TRUE). ### Request Example prop(lexington, "height") <- 15 ``` -------------------------------- ### Manage S7 Object Properties Source: https://context7.com/rconsortium/s7/llms.txt Demonstrates setting multiple properties at once and creating modified copies of objects using set_props. ```r props(r) <- list(start = 5, end = 15) r # Create modified copy with set_props() r2 <- set_props(r, start = 10, end = 20) r2 # Useful for operations that would be temporarily invalid shift <- function(x, amount) { props(x) <- list( start = x@start + amount, end = x@end + amount ) x } shift(Range(1, 10), 100) ``` -------------------------------- ### Create and Display Custom S7 Union Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/union.md Demonstrates creating a custom S7 union from two new classes and its default display. ```R foo1 <- new_class("foo1", package = NULL) foo2 <- new_class("foo2", package = NULL) new_union(foo1, foo2) ``` -------------------------------- ### method_explain - Debug Method Dispatch Source: https://context7.com/rconsortium/s7/llms.txt Shows all methods that could potentially match a generic call, which ones exist, and which will actually be called. Invaluable for debugging dispatch issues in complex class hierarchies. ```APIDOC ## method_explain - Debug Method Dispatch ### Description Shows all methods that could potentially match a generic call, which ones exist, and which will actually be called. Invaluable for debugging dispatch issues in complex class hierarchies. ### Method `method_explain(generic, args = NULL, object = NULL)` ### Parameters #### Path Parameters - **generic** (generic function) - Required - The generic function to explain. - **args** (list) - Optional - A list of class names for the arguments. - **object** (list) - Optional - A list of actual objects for the arguments. ### Request Example ```r library(S7) Foo1 <- new_class("Foo1") Foo2 <- new_class("Foo2", Foo1) add <- new_generic("add", c("x", "y")) method(add, list(Foo2, Foo1)) <- function(x, y) c(2, 1) method(add, list(Foo1, Foo1)) <- function(x, y) c(1, 1) # Explain which method will be used method_explain(add, list(Foo2, Foo2)) # Can also use objects directly method_explain(add, object = list(Foo2(), Foo2())) ``` ### Response Example ```r #> x y #> -> * Foo2 Foo1 #> * Foo1 Foo1 #> Foo2 S7_object #> Foo1 S7_object #> S7_object Foo2 #> S7_object Foo1 #> S7_object S7_object ``` ``` -------------------------------- ### Inspect S7 Class Structure Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/class.md Use `foo2` to display the structure of an S7 class, including its parent, constructor, and properties. Use `str(foo2)` for a more detailed representation including metadata like package and abstract status. ```R foo2 ``` ```R str(foo2) ``` ```R str(list(foo2)) ``` -------------------------------- ### Debug Method Dispatch with method_explain Source: https://context7.com/rconsortium/s7/llms.txt Use `method_explain()` to understand which methods match a generic call, which exist, and which will be dispatched. This is invaluable for debugging complex class hierarchies. ```r library(S7) Foo1 <- new_class("Foo1") Foo2 <- new_class("Foo2", Foo1) add <- new_generic("add", c("x", "y")) method(add, list(Foo2, Foo1)) <- function(x, y) c(2, 1) method(add, list(Foo1, Foo1)) <- function(x, y) c(1, 1) # Explain which method will be used method_explain(add, list(Foo2, Foo2)) #> x y #> -> * Foo2 Foo1 #> * Foo1 Foo1 #> Foo2 S7_object #> Foo1 S7_object #> S7_object Foo2 #> S7_object Foo1 #> S7_object S7_object # Can also use objects directly method_explain(add, object = list(Foo2(), Foo2())) ``` -------------------------------- ### Define Read-Only Computed Property with Getter Source: https://context7.com/rconsortium/s7/llms.txt Create a read-only property using a getter function. The `length` property is computed from `start` and `end` and cannot be directly set. ```r Range <- new_class("Range", properties = list( start = class_double, end = class_double, length = new_property( getter = function(self) self@end - self@start ) ) ) r <- Range(start = 1, end = 10) r@length #> [1] 9 try(r@length <- 5) # Read-only #> Error: Can't set read-only property @length ``` -------------------------------- ### Print List of S7 Classes Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/special.md Construct and print a list containing S7 objects of 'missing' and 'any' types. This shows the structure of the list and its elements. ```R str(list(m = class_missing, a = class_any)) ``` -------------------------------- ### Load S7 library Source: https://github.com/rconsortium/s7/blob/main/README.md Load the S7 package into the R session. ```r library(S7) ``` -------------------------------- ### Define S7 Classes with new_class Source: https://context7.com/rconsortium/s7/llms.txt Create formal classes with properties, inheritance, custom validators, and constructors. ```r library(S7) # Basic class with typed properties Dog <- new_class("Dog", properties = list( name = class_character, age = class_numeric )) # Create an instance lola <- Dog(name = "Lola", age = 11) lola #> #> @ name: chr "Lola" #> @ age : num 11 # Class with validator Range <- new_class("Range", properties = list( start = class_double, end = class_double ), validator = function(self) { if (length(self@start) != 1) { "@start must be a single number" } else if (length(self@end) != 1) { "@end must be a single number" } else if (self@end < self@start) { "@end must be greater than or equal to @start" } } ) Range(start = 1, end = 10) # Valid #> #> @ start: num 1 #> @ end : num 10 try(Range(start = 10, end = 1)) # Invalid - validator catches error #> Error: object is invalid: #> - @end must be greater than or equal to @start # Inheritance with parent class Pet <- new_class("Pet", properties = list( name = class_character, age = class_numeric ) ) Cat <- new_class("Cat", parent = Pet) Dog <- new_class("Dog", parent = Pet) fluffy <- Cat(name = "Fluffy", age = 5) fluffy #> #> @ name: chr "Fluffy" #> @ age : num 5 # Abstract class (cannot be instantiated) Animal <- new_class("Animal", abstract = TRUE, properties = list(species = class_character) ) # Custom constructor Range <- new_class("Range", properties = list( start = class_numeric, end = class_numeric ), constructor = function(x) { new_object(S7_object(), start = min(x, na.rm = TRUE), end = max(x, na.rm = TRUE)) } ) Range(c(10, 5, 0, 2, 5, 7)) #> #> @ start: num 0 #> @ end : num 10 ``` -------------------------------- ### Define class with various property types Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/property.md Demonstrates defining a class that includes properties of base, S3, S4, S7, and S7 union types. ```R my_class ``` -------------------------------- ### Object Property Manipulation Source: https://context7.com/rconsortium/s7/llms.txt Demonstrates setting multiple properties at once and creating modified copies of objects using `props<-` and `set_props()`. ```APIDOC ## Object Property Manipulation ### Description Set multiple properties of an S7 object at once using the `props<-` assignment or create a modified copy with `set_props()`. ### Method Assignment (`props<-`), Function Call (`set_props()`) ### Endpoint N/A (R functions) ### Request Example ```r # Set multiple properties at once (validates once at end) props(r) <- list(start = 5, end = 15) # Create modified copy with set_props() r2 <- set_props(r, start = 10, end = 20) ``` ### Response Example ```r # Output after setting props r #> #> @ start: num 5 #> @ end : num 15 # Output of modified copy r2 #> #> @ start: num 10 #> @ end : num 20 ``` ``` -------------------------------- ### Create New S7 Class Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/class.md Use `new_class()` to define new S7 classes. Ensure that arguments like `name`, `package`, and `constructor` meet the specified type and content requirements. ```R new_class(1) ``` ```R new_class("foo", 1) ``` ```R new_class("foo", package = 1) ``` ```R new_class("foo", constructor = 1) ``` ```R new_class("foo", constructor = function() { }) ``` ```R new_class("foo", validator = function() { }) ``` -------------------------------- ### Display S7 Class Details Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/class.md The `foo` object displays details about an S7 class, including whether it is abstract, its parent class, constructor, and properties. ```R foo ``` -------------------------------- ### Handle S7 class creation errors Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/external-generic.md Demonstrates error conditions when defining class properties with invalid packages or modified class objects. ```R new_class("Foo", properties = list(bar = new_class("Made Up Class", package = "t0"))) ``` ```R new_class("Foo", properties = list(bar = new_class("Made Up Class", package = "Made Up Package"))) ``` ```R modified_class <- t0::`An S7 Class` attr(modified_class, "xyz") <- "abc" new_class("Foo", properties = list(bar = modified_class)) ``` -------------------------------- ### Implement a method for a generic Source: https://github.com/rconsortium/s7/blob/main/README.md Register a method for a specific class using the method assignment operator. ```r # Add a method for our class method(inside, range) <- function(x, y) { y >= x@start & y <= x@end } inside(x, c(0, 5, 10, 15)) ``` -------------------------------- ### Accessing and setting properties with $ Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/zzz.md S7 objects do not support the $ operator for property access or assignment, suggesting the use of @ instead. ```R x$y ``` ```R x$y <- 1 ``` -------------------------------- ### new_S3_class - Declare S3 Classes for S7 Source: https://context7.com/rconsortium/s7/llms.txt Wraps an existing S3 class for use with S7, enabling method registration, property type constraints, and inheritance from S3 classes. An optional constructor and validator can be provided for creating S7 subclasses. ```APIDOC ## new_S3_class - Declare S3 Classes for S7 ### Description Wraps an existing S3 class for use with S7, enabling method registration, property type constraints, and inheritance from S3 classes. An optional constructor and validator can be provided for creating S7 subclasses. ### Method `new_S3_class(name, constructor = NULL, validator = NULL)` ### Parameters #### Path Parameters - **name** (character) - Required - The name of the S3 class. - **constructor** (function) - Optional - A function to construct the S3 object. - **validator** (function) - Optional - A function to validate the S3 object. ### Request Example ```r library(S7) # Simple declaration for method dispatch Date <- new_S3_class("Date") my_generic <- new_generic("my_generic", "x") method(my_generic, Date) <- function(x) "This is a date" my_generic(Sys.Date()) # Use S3 class as property type Event <- new_class("Event", properties = list( name = class_character, when = new_S3_class("Date") )) Event(name = "Birthday", when = Sys.Date()) # Full S3 class declaration with constructor (for inheritance) S3_factor <- new_S3_class("factor", constructor = function(.data = integer(), levels = character()) { structure(.data, levels = levels, class = "factor") }, validator = function(self) { if (!is.integer(self)) "Underlying data must be integer" } ) # S7 class extending S3 MyFactor <- new_class("MyFactor", parent = S3_factor) ``` ### Response Example ```r #> [1] "This is a date" #> #> @ name: chr "Birthday" #> @ when: Date[1:1], format: "2024-01-15" ``` ``` -------------------------------- ### Convert Between S7 Types Source: https://context7.com/rconsortium/s7/llms.txt Illustrates upcasting, downcasting, and registering custom conversion methods for S7 objects. ```r library(S7) Foo1 <- new_class("Foo1", properties = list(x = class_integer)) Foo2 <- new_class("Foo2", Foo1, properties = list(y = class_double)) # Downcasting: convert to parent class (strips extra properties) obj2 <- Foo2(x = 1L, y = 2.5) convert(obj2, to = Foo1) # Upcasting: convert to child class (new properties get defaults) obj1 <- Foo1(x = 1L) convert(obj1, to = Foo2) # Upcasting with new property values convert(obj1, to = Foo2, y = 3.14) # Custom conversion method method(convert, list(Foo1, class_integer)) <- function(from, to) { from@x } convert(Foo1(x = 42L), to = class_integer) method(convert, list(class_integer, Foo1)) <- function(from, to) { Foo1(x = from) } convert(100L, to = Foo1) ``` -------------------------------- ### super() function display and structure Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/super.md Shows how the super() function's output is displayed and structured. This is useful for understanding the representation of superclass relationships. ```r f1 <- super(foo2(), foo1) f1 ``` ```r str(list(f1)) ``` -------------------------------- ### Instantiate Abstract S7 Class Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/class.md Abstract S7 classes, defined with `abstract = TRUE`, cannot be instantiated directly. Attempting to call an abstract class like a function will result in an error. ```R foo <- new_class("foo", abstract = TRUE) foo() ``` -------------------------------- ### Declare S3 Classes for S7 with new_S3_class Source: https://context7.com/rconsortium/s7/llms.txt Wrap existing S3 classes for use with S7, enabling method registration and property type constraints. An optional constructor and validator can be provided for S7 subclasses. ```r library(S7) # Simple declaration for method dispatch Date <- new_S3_class("Date") my_generic <- new_generic("my_generic", "x") method(my_generic, Date) <- function(x) "This is a date" my_generic(Sys.Date()) #> [1] "This is a date" # Use S3 class as property type Event <- new_class("Event", properties = list( name = class_character, when = new_S3_class("Date") )) Event(name = "Birthday", when = Sys.Date()) #> #> @ name: chr "Birthday" #> @ when: Date[1:1], format: "2024-01-15" # Full S3 class declaration with constructor (for inheritance) S3_factor <- new_S3_class("factor", constructor = function(.data = integer(), levels = character()) { structure(.data, levels = levels, class = "factor") }, validator = function(self) { if (!is.integer(self)) "Underlying data must be integer" } ) # S7 class extending S3 MyFactor <- new_class("MyFactor", parent = S3_factor) ``` -------------------------------- ### Generate S7 object constructors Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/constructor.md Create constructors for basic S7 objects, including those with defined properties. ```R new_constructor(S7_object, list()) ``` ```R new_constructor(S7_object, as_properties(list(x = class_numeric, y = class_numeric))) ``` ```R foo <- new_class("foo", parent = class_character) new_constructor(foo, list()) ``` ```R foo2 <- new_class("foo2", parent = foo) new_constructor(foo2, list()) ``` -------------------------------- ### Print Any S7 Class Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/special.md Use this to print an S7 object of type 'any'. Ensure the 'class_any' variable is defined. ```R print(class_any) ``` -------------------------------- ### Generate inherited abstract class constructors Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/constructor.md Create constructors for abstract classes and extend them with additional properties. ```R foo1 <- new_class("foo1", abstract = TRUE, properties = list(x = class_double)) new_constructor(foo1, list()) ``` ```R new_constructor(foo1, as_properties(list(y = class_double))) ``` -------------------------------- ### Print S7_generic objects Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/generic.md Displays the structure and method count of S7_generic objects. ```R foo1 ``` ```R foo3 ``` ```R foo ``` -------------------------------- ### check_method: Method formals must match generic formals exactly when no '...' Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-register.md If a generic function does not include '...', the method's formal arguments must exactly match the generic's formal arguments. Any deviation will result in an error. ```R foo <- new_generic("foo", "x", function(x) S7_dispatch()) check_method(function(x, y) { }, foo) ``` -------------------------------- ### Method Not Found Error (Multiple Parameters) Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-introspect.md This error indicates that no method was found for the generic with the specified types for multiple parameters. Ensure that methods are defined for all parameter combinations. ```R method(foo2, class = list(class_integer, class_double)) ``` -------------------------------- ### Generate S3 class constructors Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/constructor.md Create constructors for existing S3 classes like factors, optionally adding properties. ```R new_constructor(class_factor, list()) ``` ```R new_constructor(class_factor, as_properties(list(x = class_numeric, y = class_numeric))) ``` -------------------------------- ### Display Base S7 Union with str() Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/union.md Illustrates how the `str()` function displays the structure of a base S7 union. ```R str(class_vector) ``` -------------------------------- ### Method Dispatch API Source: https://context7.com/rconsortium/s7/llms.txt Defines how to register and retrieve methods for generic functions, including support for S3 classes, multiple dispatch, and class unions. ```APIDOC ## method(generic, class) <- function ### Description Registers a method for a specific generic function and class signature. Supports multiple dispatch by providing a list of classes. ### Parameters - **generic** (generic) - Required - The generic function to register the method for. - **class** (class/list) - Required - The class or list of classes for dispatch. - **function** (function) - Required - The implementation of the method. ### Request Example method(greet, list(Dog, French)) <- function(animal, language) "Ouaf Ouaf" ``` -------------------------------- ### Retrieve properties Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/property.md Use this to retrieve properties that exist on an object. Errors if the property does not exist. ```R obj@x ``` -------------------------------- ### new_class - Define a New S7 Class Source: https://context7.com/rconsortium/s7/llms.txt Creates a new S7 class with formal properties, optional parent class inheritance, and custom validators. The returned object serves as both the class definition and the constructor function for creating instances. ```APIDOC ## new_class - Define a New S7 Class ### Description Creates a new S7 class with formal properties, optional parent class inheritance, and custom validators. The returned object serves as both the class definition and the constructor function for creating instances. Properties can be simple type specifications or full `new_property()` definitions with getters, setters, and validators. ### Method `new_class(name, properties = list(), parent = NULL, abstract = FALSE, constructor = NULL, validator = NULL)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **name** (character) - The name of the class. - **properties** (list) - A list of properties for the class. Each property can be a simple type specification or a `new_property()` definition. - **parent** (class) - The parent class for inheritance. - **abstract** (logical) - If TRUE, the class cannot be instantiated. - **constructor** (function) - A custom constructor function. - **validator** (function) - A custom validator function. ### Request Example ```r library(S7) # Basic class with typed properties Dog <- new_class("Dog", properties = list( name = class_character, age = class_numeric )) # Create an instance lola <- Dog(name = "Lola", age = 11) print(lola) # Class with validator Range <- new_class("Range", properties = list( start = class_double, end = class_double ), validator = function(self) { if (length(self@start) != 1) { "@start must be a single number" } else if (length(self@end) != 1) { "@end must be a single number" } else if (self@end < self@start) { "@end must be greater than or equal to @start" } } ) print(Range(start = 1, end = 10)) # Valid try(Range(start = 10, end = 1)) # Invalid - validator catches error # Inheritance with parent class Pet <- new_class("Pet", properties = list( name = class_character, age = class_numeric ) ) Cat <- new_class("Cat", parent = Pet) Dog <- new_class("Dog", parent = Pet) fluffy <- Cat(name = "Fluffy", age = 5) print(fluffy) # Abstract class (cannot be instantiated) Animal <- new_class("Animal", abstract = TRUE, properties = list(species = class_character) ) # Custom constructor Range <- new_class("Range", properties = list( start = class_numeric, end = class_numeric ), constructor = function(x) { new_object(S7_object(), start = min(x, na.rm = TRUE), end = max(x, na.rm = TRUE)) } ) print(Range(c(10, 5, 0, 2, 5, 7))) ``` ### Response #### Success Response (200) Returns the newly defined S7 class object. #### Response Example ```r Dog ``` ``` -------------------------------- ### Test execution output Source: https://github.com/rconsortium/s7/blob/main/revdep/problems.md Shows the output of running 'testthat.R' for the 'fr' package. The tests failed, with a detailed error trace indicating issues with 'fr_schema' validation. ```r # This file is part of the standard setup for testthat. # It is recommended that you do not modify it. # # Where should you do additional test configuration? # Learn more about the roles of various files in: # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview # * https://testthat.r-lib.org/articles/special-files.html ... 5. └─fr:::fr_schema(fields = purrr::imap(x, as_fr_field)) 6. └─S7::new_object(...) 7. └─S7::validate(object, recursive = !parent_validated) [ FAIL 23 | WARN 0 | SKIP 2 | PASS 9 ] Deleting unused snapshots: • write_fr_tdr/my_mtcars.csv • write_fr_tdr/tabular-data-resource.yaml Error: Test failures Execution halted ``` -------------------------------- ### Convert Between Types Source: https://context7.com/rconsortium/s7/llms.txt Details the `convert()` function for type conversions using double dispatch, including default upcasting and downcasting, and how to register custom conversion methods. ```APIDOC ## convert - Convert Between Types ### Description Converts an object from one type to another using double dispatch. S7 provides default implementations for upcasting (to child class) and downcasting (to parent class). Custom conversions require explicit method registration. ### Method Function Call (`convert`) ### Endpoint N/A (R functions) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```r library(S7) Foo1 <- new_class("Foo1", properties = list(x = class_integer)) Foo2 <- new_class("Foo2", Foo1, properties = list(y = class_double)) # Downcasting: convert to parent class (strips extra properties) obj2 <- Foo2(x = 1L, y = 2.5) convert(obj2, to = Foo1) # Upcasting: convert to child class (new properties get defaults) obj1 <- Foo1(x = 1L) convert(obj1, to = Foo2) # Upcasting with new property values convert(obj1, to = Foo2, y = 3.14) # Custom conversion method method(convert, list(Foo1, class_integer)) <- function(from, to) { from@x } convert(Foo1(x = 42L), to = class_integer) method(convert, list(class_integer, Foo1)) <- function(from, to) { Foo1(x = from) } convert(100L, to = Foo1) ``` ### Response #### Success Response (200) - **Converted Object** - The object after being converted to the target type. #### Response Example ```r # Output of downcasting #> #> @ x: int 1 # Output of upcasting (default) #> #> @ x: int 1 #> @ y: num(0) # Output of upcasting (with new property values) #> #> @ x: int 1 #> @ y: num 3.14 # Output of custom conversion (Foo1 to integer) #> [1] 42 # Output of custom conversion (integer to Foo1) #> #> @ x: int 100 ``` ``` -------------------------------- ### Invoke convert method Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/convert.md Executes a conversion on an object to a specified class. Throws an error if no matching method is found for the dispatch classes. ```R convert(obj, to = class_double) ``` -------------------------------- ### Create S3 Generic Function Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/generic-spec.md Use `as_generic()` to convert an existing function into an S3 generic function. Ensure the input is a function. ```R as_generic(function() { }) ``` -------------------------------- ### method<- - Register Methods for Generics Source: https://context7.com/rconsortium/s7/llms.txt Registers a method implementation for a specific class signature on a generic function. Works with S7, S3, and S4 generics and classes. For multiple dispatch generics, the signature is a list of classes. ```APIDOC ## method<- - Register Methods for Generics ### Description Registers a method implementation for a specific class signature on a generic function. Works with S7, S3, and S4 generics and classes. For multiple dispatch generics, the signature is a list of classes. ### Method `method(generic, signature) <- function_body` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **generic** (S7_generic) - The generic function to which the method is being added. - **signature** (character or list) - The class signature for which the method is defined. For single dispatch, this is a single class name. For multiple dispatch, this is a list of class names corresponding to the `dispatch_args` of the generic. - **function_body** (function) - The function implementation for the method. ### Request Example ```r library(S7) # Define classes and generic Dog <- new_class("Dog", properties = list(name = class_character)) Cat <- new_class("Cat", properties = list(name = class_character)) speak <- new_generic("speak", "x") # Register methods for S7 classes method(speak, Dog) <- function(x) "Woof!" method(speak, Cat) <- function(x) "Meow!" # Use the generic print(speak(Dog(name = "Rex"))) print(speak(Cat(name = "Whiskers"))) ``` ### Response #### Success Response (200) No explicit return value, but the method is registered with the generic function. #### Response Example (No direct response, but subsequent calls to the generic function will use the registered method.) ``` -------------------------------- ### Display Empty S7 Object Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/class.md An S7 object with defined properties is displayed showing default values. `str(list(foo()))` provides a detailed list representation. ```R foo <- new_class("foo", properties = list(x = class_double, y = class_double), package = NULL) foo() ``` ```R str(list(foo())) ``` -------------------------------- ### Method Not Found Error (Class) Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-introspect.md This error is raised when no method can be found for the specified generic and class combination. Ensure a method is registered for the given signature. ```R method(foo, class = class_integer) ``` -------------------------------- ### Check signature type for method registration Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-register.md The signature argument for method registration must be a valid S7 class, an S4 class object, or a base class. Providing an invalid type like a double will cause an error. ```R method(foo, 1) <- (function(x) ...) ``` -------------------------------- ### Inspect S7 class arguments Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/external-generic.md Inspects arguments for classes with hard and soft dependencies. ```R args(Foo) ``` ```R args(t2::`An S7 Class 2`) ``` ```R args(t2:::`An Internal Class`) ``` -------------------------------- ### as_signature requires correct list length for multiple dispatch Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-register.md For multiple dispatch generics, `as_signature()` requires the signature to be a list of the correct length. Providing a non-list or a list of incorrect length will result in an error. ```R as_signature(class_character, foo) ``` ```R as_signature(list(class_character), foo) ``` -------------------------------- ### Subsetting S7 objects with [[ Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/zzz.md S7 objects are not subsettable, resulting in an error when using the [[ operator. ```R x <- new_class("foo")() x[[1]] ``` ```R x[[1]] <- 1 ``` -------------------------------- ### Define and Use Generic Function with Methods Source: https://context7.com/rconsortium/s7/llms.txt Define a generic function and its methods for different classes. Use this to implement polymorphic behavior. ```R stringify <- new_generic("stringify", "x") method(stringify, class_numeric) <- function(x) paste("Number:", x) method(stringify, class_character) <- function(x) paste("Text:", x) method(stringify, class_logical) <- function(x) paste("Bool:", x) ``` ```R stringify(42) #> [1] "Number: 42" stringify("hello") #> [1] "Text: hello" stringify(TRUE) #> [1] "Bool: TRUE" ``` -------------------------------- ### Method Not Found Error (Multiple Parameters with Object) Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-introspect.md This error occurs when no method is found for a generic with multiple parameters when dispatched using objects. Confirm that methods are registered for the provided object types. ```R method(foo2, object = list(1L, 2)) ``` -------------------------------- ### Handle Non-Function Input for as_generic Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/generic-spec.md The `as_generic()` function requires a function as input. Providing a non-function value, like a double, will result in an error. ```R as_generic(1) ``` -------------------------------- ### Handle default constructor errors Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/S3.md Triggers an error when an S3 class lacks a defined constructor. ```R class_construct(new_S3_class("foo"), 1) ``` -------------------------------- ### Register S7 method for S3 generic Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-register.md When registering an S7 method for an S3 generic, the signature must be an S7 class. Using an S3 class will result in an error. ```R method(sum, new_S3_class("foo")) <- (function(x, ...) "foo") ``` -------------------------------- ### Create S3 class with new_S3_class Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/S3.md Defines a new S3 class using a character vector of class names. ```R new_S3_class(c("ordered", "factor")) ``` -------------------------------- ### Call Superclass Methods with super() Source: https://context7.com/rconsortium/s7/llms.txt Use `super()` to call a method from a specified superclass. This is crucial for extending parent class behavior without code duplication. It only affects the immediate generic call. ```r library(S7) Foo1 <- new_class("Foo1", properties = list(x = class_numeric, y = class_numeric)) Foo2 <- new_class("Foo2", Foo1, properties = list(z = class_numeric)) total <- new_generic("total", "x") method(total, Foo1) <- function(x) x@x + x@y method(total, Foo2) <- function(x) total(super(x, to = Foo1)) + x@z total(Foo2(x = 1, y = 2, z = 3)) #> [1] 6 # super() only affects the next generic call bar1 <- new_generic("bar1", "x") method(bar1, Foo1) <- function(x) 1 method(bar1, Foo2) <- function(x) 2 bar2 <- new_generic("bar2", "x") method(bar2, Foo1) <- function(x) c(1, bar1(x)) method(bar2, Foo2) <- function(x) c(2, bar1(x)) obj <- Foo2(1, 2, 3) bar2(obj) #> [1] 2 2 # convert() affects every generic call bar2(convert(obj, to = Foo1)) #> [1] 1 1 # super() only affects the immediate bar2 call, not nested bar1 bar2(super(obj, to = Foo1)) #> [1] 1 2 ``` -------------------------------- ### Combine S7 objects error Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/class.md Attempting to combine S7 class objects using c() results in an error. ```R c(foo1, foo1) ``` -------------------------------- ### Subsetting S7 objects with [ Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/zzz.md S7 objects are not subsettable, resulting in an error when using the [ operator. ```R x <- new_class("foo")() x[1] ``` ```R x[1] <- 1 ``` -------------------------------- ### Calling a wrapper function that triggers method dispatch Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/R-lt-4-3/method-dispatch.md This snippet shows the call to a wrapper function. The subsequent error indicates that the method dispatch failed because an argument was missing. ```R foo_wrapper() ``` -------------------------------- ### Validate S7 Objects Source: https://context7.com/rconsortium/s7/llms.txt Shows how to explicitly validate objects and use helper functions to manage validation timing during modifications. ```r library(S7) Range <- new_class("Range", properties = list(start = class_double, end = class_double), validator = function(self) { if (self@start >= self@end) "start must be smaller than end" } ) r <- Range(1, 10) # Low-level modification bypasses validation attr(r, "start") <- 20 # Explicit validation catches the problem try(validate(r)) # valid_eventually - disable validation, modify, then validate rightwards <- function(r, x) { valid_eventually(r, function(object) { object@start <- object@start + x object@end <- object@end + x object }) } rightwards(Range(1, 10), 100) # valid_implicitly - skip final validation (use carefully) fast_shift <- function(r, x) { valid_implicitly(r, function(object) { attr(object, "start") <- object@start + x attr(object, "end") <- object@end + x object }) } ``` -------------------------------- ### Vignette re-building error: creating_a_tabular-data-resource.Rmd Source: https://github.com/rconsortium/s7/blob/main/revdep/problems.md Error encountered while re-building the 'creating_a_tabular-data-resource.Rmd' vignette. The failure is due to an invalid '' object. ```r Error(s) in re-building vignettes: ... --- re-building ‘creating_a_tabular-data-resource.Rmd’ using rmarkdown Quitting from lines 48-57 [unnamed-chunk-4] (creating_a_tabular-data-resource.Rmd) Error: processing vignette 'creating_a_tabular-data-resource.Rmd' failed with diagnostics: object is invalid: - all items in @fields should be fr_field objects --- failed re-building ‘creating_a_tabular-data-resource.Rmd’ ``` -------------------------------- ### Display S7 property object Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/property.md Printing an S7 property object shows its name, class, and whether getter, setter, validator, or default are defined. ```R print(x) ``` ```R str(list(x)) ``` -------------------------------- ### Define Method for Class Union Source: https://context7.com/rconsortium/s7/llms.txt Register a method for a union of classes. This `bizarro` method applies to all `class_numeric` types. ```r bizarro <- new_generic("bizarro", "x") method(bizarro, class_numeric) <- function(x) rev(x) bizarro(1:5) #> [1] 5 4 3 2 1 ``` -------------------------------- ### Overwrite existing S7 method Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-register.md Registering a method for an existing generic and signature combination will overwrite the previous method. This is useful for updating method implementations. ```R method(foo, class_character) <- (function(x) "c") method(foo, class_character) <- (function(x) "c") ``` -------------------------------- ### check_method: Method arguments must match generic Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/method-register.md This check ensures that the arguments of the method being registered are compatible with the generic function's signature. Mismatched arguments, including missing or extra ones, will cause an error. ```R check_method(function(y) { }, foo) ``` -------------------------------- ### Skip validation with `set_props(.check = FALSE)` Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/property.md Use `set_props(.check = FALSE)` to skip validation when setting properties, similar to `validate(obj, check = FALSE)`. ```R validate(obj2) ``` -------------------------------- ### Prevent Inheritance from Environment Source: https://github.com/rconsortium/s7/blob/main/tests/testthat/_snaps/class.md S7 classes cannot inherit from environments. Use `new_class()` with a valid parent class. ```R new_class("test", parent = class_environment) ```