Problem raised from: when we define the coercion method using setAs("DelayedDataFrame", "DataFrame") (DelayedDataFrame contains DataFrame with one additional slot lazyIndex), and construct a VariantExperiment object by ve <- VariantExperiment(colData=DelayedDataFrame()), then the col(VE) returns a DataFrame instead of a DelayedDataFrame. After discussiong this with Herve, there are 3 problems identified:

  1. why would new("B", x="") call as(..., "A", strict=FALSE) on the incoming slot value?
  2. as() not behaving as expected, because a call like this as(x, "A", strict=FALSE), as() should detect that x extends A and just return x. It should not even call the coercion method from Aa to A.
  3. you can't see the automatic coercion method until you've used it i.e. selectMethod("coerce", c("Aa", "A")) will fail if you've not called as(new("Aa") "A") before. All these problems have been around for years. I started to report them in the R bug tracker at some point but stopped after a while because nobody would take care of them. (Herve)

So a workaround this led us to a temporary fix of the above problems, where we explicitly define the coercion method using setMethod("coerce", c("Aa", "A")) by adding the strict argument for checking (if !strict && is(from, "A")) inside the coercion method. But eventually, the checking should be implemented inside as(..., "A", strict=FALSE) method, and remove the strict argument from the standard coercion method by using setAs.

5/10/2018, work around about coercion method with some demo code.

setClass("A", representation(x = "numeric"))
setClass("Aa", contains = "A")
setClass("B", representation(x = "A"))
class(new("B", x = new("Aa"))@x)
## [1] "Aa"
## attr(,"package")
## [1] ".GlobalEnv"
as(new("Aa"), "A", strict=FALSE)
## An object of class "Aa"
## Slot "x":
## numeric(0)
selectMethod("coerce", c("Aa", "A"))
## Method Definition:
## function (from, to = "A", strict = TRUE) 
## if (strict) {
##     class(from) <- "A"
##     from
## } else from
## <bytecode: 0x4328370>

## Signatures:
##         from to 
## target  "Aa" "A"
## defined "Aa" "A"

when explicitly define coercion method between Aa and A, the coercion method ignores the "strict" argument.

setAs("Aa", "A", function(from) new("A", x = from@x))
## the standard way to define coercion method (using setAs) does not let you handle the "strict" argument. And when calling new(), it calls as(new("Aa"), "A", strict=FALSE) (problem 1, "new" calls "as"), but the coercion method could only return "A" with strict=TRUE. (problem 2). So we can only define the coercion method using setMethod("coerce", c("Aa", "A")), and add the "strict" argument here. 
class(new("B", x=new("Aa"))@x)
## [1] "A"
## attr(,"package")
## [1] ".GlobalEnv"
as(new("Aa"), "A", strict=FALSE)
## An object of class "A"
## Slot "x":
## numeric(0)
selectMethod("coerce", c("Aa", "A"))  ## "strict" argument ignored. 
## Method Definition:
## function (from, to = "A", strict = TRUE) 
## new("A", x = from@x)
## <bytecode: 0x1f50da8>

## Signatures:
##         from to 
## target  "Aa" "A"
## defined "Aa" "A"

work around

setMethod("coerce", c("Aa", "A"),
    function(from, to="A", strict=TRUE) {
        if (!strict && is(from, "A"))
            return(from)
        new("A", x=from@x)
    }
)
class(new("B", x = new("Aa"))@x)
## [1] "Aa"
## attr(,"package")
## [1] ".GlobalEnv"


Bioconductor/DelayedDataFrame documentation built on Nov. 2, 2024, 7:21 a.m.