Do not write an initialize method, write a public constructor
(.Part
: a constructor to be used by your code only, not the user). The public constructor's job is to transform user arguments to a consistent form for class methods
.Part<-setRefClass(Class = "Part"
,fields = c(var1 = "ANY", var2 = "character"))
Use setOldClass
to enable class dispatch
setOldClass(c("XMLInternalElementNode", "XMLInternalNode",
"XMLAbstractNode"))
Write your public constructor as an S4 generic and methods
setGeneric("Part", function(x, ...) standardGeneric("Part"))
setMethod("Part", "missing", function(x, ...) {
.Part()
})
setMethod("Part", "XMLInternalNode", function(x, ...) {
attr<-xmlAttrs(x)
var1 <- if (!is.na(attr["var1"])) attr["var1"] else vector()
var2 <- if (!is.na(attr["var2"])) attr["var2"] else character()
.Part(var1=var1, var2=var2, ...)
})
setMethod("Part", "ANY", function(x, var2, ...) {
.Part(var1=x, var2=var2, ...)
})
Add a copy constructor if desired
setMethod("Part", "Part", function(x, ...) x$copy())
or if your own initialize
method does something additional and conforms to the contract of the default initialize
method (which acts as a copy constructor too) use
setMethod("Part", "Part", function(x, ...) .Part(x, ...))
Add any common code shared by constructors to the initialize
method, being sure that your initialize
method acts as a copy constructor and works when invoked without any arguments.
Make sure that simple test cases work
library(XML)
Part()
Part(TRUE, "var2")
txt <- "<doc> <part var2=\"abc\"/> </doc>"
node <- xmlTreeParse(txt, useInternalNodes = TRUE)[["//part"]]
p1 <- Part(node)
p2 <- Part(p1)
p1$var2 <- "xyz"
p2$var2 ## "abc"