Dear all
Below is the code for "scriptPreFilter.R" which gives the following result:
> source("scriptPreFilter.R")
> prefltr <- new("PreFilter", mad=c(0.5,0.01))
[1] "------initialize:PreFilter------"
[1] "------initialize:Filter------"
> str(prefltr)
Formal class 'PreFilter' [package ".GlobalEnv"] with 2 slots
..@ mad :List of 2
.. ..$ cutoff : num 0.5
.. ..$ epsilon: num 0.01
..@ numfilters: num 1
It seems that everything is ok, the results are as expected.
However, my problem is that copying the identical code to my package
results in an error:
> prefltr <- new("PreFilter", mad=c(0.5,0.01))
[1] "------setValidity:Filter------"
Error in validObject(.Object) :
invalid class "PreFilter" object: invalid object for slot "mad" in
class "PreFilter": got class "numeric", should be or extend class "list"
The following code avoids the error and gives the result:
> prefltr <- new("PreFilter", mad=list(0.5,0.01))
[1] "------setValidity:Filter------"
[1] "------setValidity:PreFilter------"
> str(prefltr)
Formal class 'PreFilter' [package "xps"] with 11 slots
..@ mad :List of 2
.. ..$ : num 0.5
.. ..$ : num 0.01
..@ numfilters : num 0
This is only partly correct, e.g. numfilters is 0.
Only the following code gives the correct result:
> prefltr <- new("PreFilter")
> madFilter(prefltr) <- c(0.5,0.01)
> str(prefltr)
Formal class 'PreFilter' [package "xps"] with 11 slots
..@ mad :List of 2
.. ..$ cutoff : num 0.5
.. ..$ epsilon: num 0.01
..@ numfilters : num 1
As you see, the loading "scriptPreFilter.R" calls method initialize but
not setValidity.
In contrast, loading my package as library calls setValidity but not
initialize.
My question is:
- Why can the identical code behave differently when put in a package?
- How can I ensure, that initialize gets also called in my package?
> sessionInfo()
R version 2.6.1 (2007-11-26)
i386-apple-darwin8.10.1
locale:
C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] xps_0.4.0
loaded via a namespace (and not attached):
[1] rcompgen_0.1-17
Best regards and Merry Christmas
Christian
_._._._._._._._._._._._._._._._
C.h.i.s.t.i.a.n S.t.r.a.t.o.w.a
V.i.e.n.n.a A.u.s.t.r.i.a
e.m.a.i.l: cstrato at aon.at
_._._._._._._._._._._._._._._._
------- BEGIN: scriptPreFilter.R ---------
setClass("Filter",
representation(numfilters = "numeric"),
prototype(numfilters = 0)
)
setClass("PreFilter",
representation(mad = "list"),
contains=c("Filter"),
prototype(mad = list())
)
setGeneric("madFilter", function(object) standardGeneric("madFilter"))
setGeneric("madFilter<-", function(object, value)
standardGeneric("madFilter<-"))
"initialize.Filter" <- function(.Object, ...)
{
print("------initialize:Filter------")
.Object <- callNextMethod(.Object, ...)
.Object
}
setMethod("initialize", "Filter", initialize.Filter)
setValidity("Filter",
function(object) {
print("------setValidity:Filter------")
msg <- NULL
if (is.null(msg)) TRUE else msg
}
)
"initialize.PreFilter" <- function(.Object, mad = list(), ...)
{
print("------initialize:PreFilter------")
.Object at numfilters <- 0
if (length(mad)) madFilter(.Object) <- unlist(mad)
.Object <- callNextMethod(.Object, ...)
.Object
}
setMethod("initialize", "PreFilter", initialize.PreFilter)
setValidity("PreFilter",
function(object) {
print("------setValidity:PreFilter------")
msg <- NULL
if (is.null(msg)) TRUE else msg
}
)
setMethod("madFilter", signature(object="PreFilter"),
function(object) object at mad
)
setReplaceMethod("madFilter", signature(object="PreFilter",
value="numeric"),
function(object, value) {
if (length(value) == 1) {
value[2] <- 0.01
} else if (length(value) != 2) {
stop(paste(sQuote("mad"), "must have <cutoff,epsilon>"))
}#if
if (length(object at mad) == 0) {
object at numfilters <- object at numfilters + 1
}#if
object at mad <- list(cutoff = as.double(value[1]),
epsilon = as.double(value[2]))
return(object)
}
)
------- END: scriptPreFilter.R ---------
Problem with initialize of S4 classes
3 messages · cstrato, Martin Morgan
Hi Christian --
Does your package have a name space, but not export 'initialize'?
Calling 'new' will then go directly to the default constructors,
generating the error. A different solution would be to define a
constructor in your package
PreFilter <- function(...) {
new("PreFilter", ...)
}
so that your user would not have to know about the details of calling
new, you could provide helpful arguments to your constructor, and
'pre-processing' of arguments can be done (in the constructor) before
calling 'new' (I find this helpful, to avoid have to be too careful
when constructing initialize methods that deal with both the class and
classes derived from the class).
Martin
cstrato <cstrato at aon.at> writes:
Dear all Below is the code for "scriptPreFilter.R" which gives the following result:
> source("scriptPreFilter.R")
> prefltr <- new("PreFilter", mad=c(0.5,0.01))
[1] "------initialize:PreFilter------" [1] "------initialize:Filter------"
> str(prefltr)
Formal class 'PreFilter' [package ".GlobalEnv"] with 2 slots ..@ mad :List of 2 .. ..$ cutoff : num 0.5 .. ..$ epsilon: num 0.01 ..@ numfilters: num 1 It seems that everything is ok, the results are as expected. However, my problem is that copying the identical code to my package results in an error:
> prefltr <- new("PreFilter", mad=c(0.5,0.01))
[1] "------setValidity:Filter------" Error in validObject(.Object) : invalid class "PreFilter" object: invalid object for slot "mad" in class "PreFilter": got class "numeric", should be or extend class "list" The following code avoids the error and gives the result:
> prefltr <- new("PreFilter", mad=list(0.5,0.01))
[1] "------setValidity:Filter------" [1] "------setValidity:PreFilter------"
> str(prefltr)
Formal class 'PreFilter' [package "xps"] with 11 slots ..@ mad :List of 2 .. ..$ : num 0.5 .. ..$ : num 0.01 ..@ numfilters : num 0 This is only partly correct, e.g. numfilters is 0. Only the following code gives the correct result:
> prefltr <- new("PreFilter")
> madFilter(prefltr) <- c(0.5,0.01)
> str(prefltr)
Formal class 'PreFilter' [package "xps"] with 11 slots ..@ mad :List of 2 .. ..$ cutoff : num 0.5 .. ..$ epsilon: num 0.01 ..@ numfilters : num 1 As you see, the loading "scriptPreFilter.R" calls method initialize but not setValidity. In contrast, loading my package as library calls setValidity but not initialize. My question is: - Why can the identical code behave differently when put in a package? - How can I ensure, that initialize gets also called in my package?
> sessionInfo()
R version 2.6.1 (2007-11-26)
i386-apple-darwin8.10.1
locale:
C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] xps_0.4.0
loaded via a namespace (and not attached):
[1] rcompgen_0.1-17
Best regards and Merry Christmas
Christian
_._._._._._._._._._._._._._._._
C.h.i.s.t.i.a.n S.t.r.a.t.o.w.a
V.i.e.n.n.a A.u.s.t.r.i.a
e.m.a.i.l: cstrato at aon.at
_._._._._._._._._._._._._._._._
------- BEGIN: scriptPreFilter.R ---------
setClass("Filter",
representation(numfilters = "numeric"),
prototype(numfilters = 0)
)
setClass("PreFilter",
representation(mad = "list"),
contains=c("Filter"),
prototype(mad = list())
)
setGeneric("madFilter", function(object) standardGeneric("madFilter"))
setGeneric("madFilter<-", function(object, value)
standardGeneric("madFilter<-"))
"initialize.Filter" <- function(.Object, ...)
{
print("------initialize:Filter------")
.Object <- callNextMethod(.Object, ...)
.Object
}
setMethod("initialize", "Filter", initialize.Filter)
setValidity("Filter",
function(object) {
print("------setValidity:Filter------")
msg <- NULL
if (is.null(msg)) TRUE else msg
}
)
"initialize.PreFilter" <- function(.Object, mad = list(), ...)
{
print("------initialize:PreFilter------")
.Object at numfilters <- 0
if (length(mad)) madFilter(.Object) <- unlist(mad)
.Object <- callNextMethod(.Object, ...)
.Object
}
setMethod("initialize", "PreFilter", initialize.PreFilter)
setValidity("PreFilter",
function(object) {
print("------setValidity:PreFilter------")
msg <- NULL
if (is.null(msg)) TRUE else msg
}
)
setMethod("madFilter", signature(object="PreFilter"),
function(object) object at mad
)
setReplaceMethod("madFilter", signature(object="PreFilter",
value="numeric"),
function(object, value) {
if (length(value) == 1) {
value[2] <- 0.01
} else if (length(value) != 2) {
stop(paste(sQuote("mad"), "must have <cutoff,epsilon>"))
}#if
if (length(object at mad) == 0) {
object at numfilters <- object at numfilters + 1
}#if
object at mad <- list(cutoff = as.double(value[1]),
epsilon = as.double(value[2]))
return(object)
}
)
------- END: scriptPreFilter.R ---------
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Martin Morgan Computational Biology / Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109 Location: Arnold Building M2 B169 Phone: (206) 667-2793
Dear Martin Thank you for your comments! You are correct, I have a name space but did not export "initialize", since I thought that a user will never need to use it. I will also try your suggestion to define a constructor in my package, this seems to me to be a great idea. Merry Christmas Christian
Martin Morgan wrote:
Hi Christian --
Does your package have a name space, but not export 'initialize'?
Calling 'new' will then go directly to the default constructors,
generating the error. A different solution would be to define a
constructor in your package
PreFilter <- function(...) {
new("PreFilter", ...)
}
so that your user would not have to know about the details of calling
new, you could provide helpful arguments to your constructor, and
'pre-processing' of arguments can be done (in the constructor) before
calling 'new' (I find this helpful, to avoid have to be too careful
when constructing initialize methods that deal with both the class and
classes derived from the class).
Martin
cstrato <cstrato at aon.at> writes:
Dear all Below is the code for "scriptPreFilter.R" which gives the following result:
> source("scriptPreFilter.R")
> prefltr <- new("PreFilter", mad=c(0.5,0.01))
[1] "------initialize:PreFilter------" [1] "------initialize:Filter------"
> str(prefltr)
Formal class 'PreFilter' [package ".GlobalEnv"] with 2 slots ..@ mad :List of 2 .. ..$ cutoff : num 0.5 .. ..$ epsilon: num 0.01 ..@ numfilters: num 1 It seems that everything is ok, the results are as expected. However, my problem is that copying the identical code to my package results in an error:
> prefltr <- new("PreFilter", mad=c(0.5,0.01))
[1] "------setValidity:Filter------" Error in validObject(.Object) : invalid class "PreFilter" object: invalid object for slot "mad" in class "PreFilter": got class "numeric", should be or extend class "list" The following code avoids the error and gives the result:
> prefltr <- new("PreFilter", mad=list(0.5,0.01))
[1] "------setValidity:Filter------" [1] "------setValidity:PreFilter------"
> str(prefltr)
Formal class 'PreFilter' [package "xps"] with 11 slots ..@ mad :List of 2 .. ..$ : num 0.5 .. ..$ : num 0.01 ..@ numfilters : num 0 This is only partly correct, e.g. numfilters is 0. Only the following code gives the correct result:
> prefltr <- new("PreFilter")
> madFilter(prefltr) <- c(0.5,0.01)
> str(prefltr)
Formal class 'PreFilter' [package "xps"] with 11 slots ..@ mad :List of 2 .. ..$ cutoff : num 0.5 .. ..$ epsilon: num 0.01 ..@ numfilters : num 1 As you see, the loading "scriptPreFilter.R" calls method initialize but not setValidity. In contrast, loading my package as library calls setValidity but not initialize. My question is: - Why can the identical code behave differently when put in a package? - How can I ensure, that initialize gets also called in my package?
> sessionInfo()
R version 2.6.1 (2007-11-26) i386-apple-darwin8.10.1 locale: C attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] xps_0.4.0 loaded via a namespace (and not attached): [1] rcompgen_0.1-17 Best regards and Merry Christmas Christian _._._._._._._._._._._._._._._._ C.h.i.s.t.i.a.n S.t.r.a.t.o.w.a V.i.e.n.n.a A.u.s.t.r.i.a e.m.a.i.l: cstrato at aon.at _._._._._._._._._._._._._._._._