Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validator not triggered when new_class derives from base class #495

Open
tschwarzl opened this issue Nov 15, 2024 · 2 comments
Open

Validator not triggered when new_class derives from base class #495

tschwarzl opened this issue Nov 15, 2024 · 2 comments

Comments

@tschwarzl
Copy link

tschwarzl commented Nov 15, 2024

Related to #413

The validator is also not triggered when new_class derives from a base type as showcased in this example e.g.:

list_derived_class <- new_class(
  "list_derived_class",
  parent = class_list,
  validator = function(self) {
    if(length(self) > 0)
      "raising non-empty test error"
  }
)

x <- list_derived_class()
x[["A"]] = 1
x[["B"]] = 2

This is rather counter intuitive behavior when deriving from a class.

One suggestion would be that S7_base_class provided by e.g. class_list would overwrite the base setters installing a hook to trigger the validator.

@t-kalinowski
Copy link
Member

t-kalinowski commented Nov 15, 2024

Thanks for opening this.

The issue is that [[<- doesn’t interact with any parts of S7 in this case, so it doesn’t trigger validation.

For example, in the snippet above, class(x) is c("list_derived_class", "list", "S7_object"), and the [[<- method for list is the one being invoked.

One workaround is to define a [[<- method on the S7 class that explicitly calls validate().

In the example method below, I’m using NextMethod() to delegate to the [[<- method for list. Note that using NextMethod() with S7 is technically “off-label” usage; the ultimate intention is for S7_data() and S7::super() to address this need. However, S7_data() needs a little more work, and NextMethod() can be a reliable solution in the interim.

library(S7)

list_derived_class <- new_class(
  "list_derived_class",
  parent = class_list,
  validator = function(self) {
    if(length(self) > 0)
      "raising non-empty test error"
  }
)

method(`[[<-`, list_derived_class) <- function(x, ...) validate(NextMethod())

x <- list_derived_class()
x[["A"]] = 1
#> Error: <list_derived_class> object is invalid:
#> - raising non-empty test error

Created on 2024-11-15 with reprex v2.1.1

@tschwarzl
Copy link
Author

Thank you, @t-kalinowski for the nice explanation and the workaround.

It would be very nice if when the S7_base_class would provide a wrapper around "list" with validate() call in place - e.g. a S7_list which overwrites [[<-

c("list_derived_class", "S7_list", "list", "S7_object")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants