I have a reference class, one of the fields for which is a 'units' object from the R units package. My initial class definition looked like this:
MyClass =
setRefClass(
"MyClass",
fields = list(units_value = "numeric")
)
uv = units::as_units(10, 'cm')
mc = MyClass(units_value = uv)
Which threw the following error:
Error: invalid assignment for reference class field ‘units_value’, should be from class “numeric” or a subclass (was class “units”)
So I tried to set the field class to units
like so:
MyClass =
setRefClass(
"MyClass",
fields = list(units_value = "units")
)
uv = units::as_units(10, 'cm')
mc = MyClass(units_value = uv)
But this throws a whole new error:
Error in refClassInformation(Class, contains, fields, methods, where) :
class “units” for field ‘units_value’ is not defined
For the moment I've settled for using a non-typed class constructor, but this seems like such a simple problem that it's hard for me to believe there's no way to construct a Reference Class with a units object as a field. Does anyone know how to accomplish this?
CodePudding user response:
"units"
is an S3 class, so doesn't have a formal class definition. To get an S3 class to be represented inside an S4 or reference class, you need to register it first as a formally defined class using setOldClass
We can see that there is no formal class definition for "units" if we do:
library(units)
getClassDef("units")
#> NULL
But if we use setOldClass
, we can see it becomes registered:
setOldClass("units")
getClassDef("units")
#> Virtual Class "units" [in ".GlobalEnv"]
#>
#> Slots:
#>
#> Name: .S3Class
#> Class: character
#>
#> Extends: "oldClass"
This now allows your second code block to work as expected:
MyClass =
setRefClass(
"MyClass",
fields = list(units_value = "units")
)
uv = units::as_units(10, 'cm')
mc = MyClass(units_value = uv)
mc
#> Reference class object of class "MyClass"
#> Field "units_value":
#> 10 [cm]
The alternative is to set the class as "ANY" instead of "units", but this always feels like a last resort if you are trying to stick to OOP principles.
Created on 2022-12-15 with reprex v2.0.2