Use S4 generics and methods for polymorphism
setGeneric("Add", function(x, y) standardGeneric("Add")) setMethod(Add, c("numeric", "numeric"), function(x, y) x + y) setMethod(Add, c("character", "character"), function(x, y) paste0(x, y))
so
> Add(1, 2) [1] 3 > Add("hello ", "world") [1] "hello world" > Add("hello ", 2) Error in (function (classes, fdef, mtable) : unable to find an inherited method for function 'Add' for signature '"character", "numeric"'
One idea to use this generic in a reference class is
A <- setRefClass("A", fields=list(x="ANY"), methods=list( getX=function() { .self$x }, setX=function(x) { .self$x <- x .self }, addX=function(y) { setX(Add(getX(), y)) }, show=function() { cat("class:", class(.self), "\nx:", getX(), "\n") }))
with appropriate dispatch for functional program style:
setMethod(Add, c("A", "ANY"), function(x, y) x$addX(y)) setMethod(Add, c("A", "A"), function(x, y) x$addX(y$getX()))
(maybe for functional programming it makes more sense to implement
$addX()
asA(.self, x=Add(x$getX(), y))
, i.e., creating a clone of x?) to allow for> Add(A(x=1), A(x=2)) class: A x: 3 > Add(A(x="hello "), "world") class: A x: hello world > A(x=2)$addX(3) class: A x: 5
though not
A(x=1)$addX(A(x=2))
See this answer for one approach to returning field values:
B = setRefClass("B", fields=c(var1="list", var2="character"), methods=list(getFields=function(values) { flds = names(getRefClass()$fields()) if (!missing(values)) flds = flds[flds %in% values] result = setNames(vector("list", length(flds)), flds) for (fld in flds) result[[fld]] = .self[[fld]] result }))
One way to invoke in a functional way requires a separate implementation, e.g.,
setGeneric("getFields", function(x, ...) standardGeneric("getFields")) setMethod(getFields, "B", function(x, ...) x$getFields(...)) setMethod(getFields, "list", function(x, ...) lapply(x, getFields, ...))
Your class A example is incomplete.
A <- setRefClass("A", methods=list(initialize=function(...) { message("hello A") callSuper(...) }))
and then
> A$trace("initialize", browser) Tracing reference method "initialize" for class "A" [1] "initialize" > A() Tracing .Object$initialize(...) on entry Called from: eval(expr, envir, enclos) Browse[1]> n debug: { message("hello A") callSuper(...) } Browse[2]> n debug: message("hello A") Browse[2]>
Programming with Reference Class
-
28-06-2022 - |
Question
How to define several polymorph constructors and functions like
function Add( x, y : Integer ) : Integer; begin Add := x + y end; function Add( s, t : String ) : String; begin Add := Concat( s, t ) end; begin Writeln(Add(1, 2)); Writeln(Add('Hello, ', 'World!')); end.
Can I do this only by case decission like
A<-setRefClass(Class = "A"
,fields = list(var1="character")
,methods = list(setFields=A.setFields
,initialize=function(var1) {
if(isClass(var1,"B"))
.self$var1<-as.character(var1$getFields("var1"))
else{
.self$var1<-as.character(var1)
}
.self
})
)
How to combine functional programming with objectorientated prgramming. So if I would call the functions getFields(vecB), where vecB is a vector or list of objects B. The return should be the values of each object?
B.getFields<-function(...,values){ vars<-mget(names(.refClassDef@fieldClasses), envir = attr(.self, ".xData")) if(missing(values)) return(vars) if(length(vars)==1) return(vars[[1]]) return(vars[names(vars) %in% values]) } B<-setRefClass(Class = "B" ,fields = list(var1 = "character") )
How to debug e.g. the function initialize from class A? I tried
A$trace("initialize") a<-A$new("ABC") initial<-a$initialize trace(initial,browser,where=A)
but it doesnt work.
Solution
OTHER TIPS
Here's a previous discussion on polymorphisms in R: What are the suggested practices for function polymorphism in R?
The way to concatenate a string is with paste.
paste("Hello, ","world",sep="")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow