From lawrence.michael at gene.com  Fri Mar 18 23:28:14 2016
From: lawrence.michael at gene.com (Michael Lawrence)
Date: Fri, 18 Mar 2016 15:28:14 -0700
Subject: [Rd] unary class union of an S3 class
In-Reply-To: <56EC78DA.2010803@fredhutch.org>
References: <56EC78DA.2010803@fredhutch.org>
Message-ID: <CAOQ5NydT6YjFRw5xCTueA-e5DjM8pi0Y2fqUUb=PvJyJmtpeag@mail.gmail.com>

On Fri, Mar 18, 2016 at 2:53 PM, Herv? Pag?s <hpages at fredhutch.org> wrote:

> Hi,
>
> Short story
> -----------
>
>   setClassUnion("ArrayLike", "array")
>
>   showClass("ArrayLike")  # no slot
>
>   setClass("MyArrayLikeConcreteSubclass",
>       contains="ArrayLike",
>       representation(stuff="ANY")
>   )
>
>   showClass("MyArrayLikeConcreteSubclass") # 2 slots!!
>
> That doesn't seem right.
>
> Long story
> ----------
>
> S4 provides at least 3 ways to create a little class hierarchy
> like this:
>
>        FooLike ............. virtual class with no slot
>         ^   ^
>         |   |
>       foo   anotherfoo ..... 2 concrete subclasses
>
> (1) The "standard" way: define FooLike first, then foo and anotherfoo
> as subclasses of FooLike:
>
>   setClass("FooLike")
>
>   setClass("foo",
>       contains="FooLike",
>       representation(stuff="ANY")
>   )
>
>   setClass("anotherfoo",
>       contains="FooLike",
>       representation(stuff="ANY")
>   )
>
>   showClass("FooLike")    # displays foo and anotherfoo as
>                           # known subclasses
>
>   x1 <- new("foo")
>   is(x1, "foo")           # TRUE
>   is(x1, "FooLike")       # TRUE
>   is(x1, "anotherfoo")    # FALSE
>
>   x2 <- new("anotherfoo")
>   is(x2, "anotherfoo")    # TRUE
>   is(x2, "FooLike")       # TRUE
>   is(x2, "foo")           # FALSE
>
> Everything works as expected.
>
> (2) Using a class union: define foo and anotherfoo first, then FooLike
> as the union of foo and anotherfoo:
>
>   setClass("foo", representation(stuff="ANY"))
>   setClass("anotherfoo", representation(stuff="ANY"))
>   setClassUnion("FooLike", c("foo", "anotherfoo"))
>
>   showClass("FooLike")    # displays foo and anotherfoo as
>                           # known subclasses
>
> (3) Using a *unary* class union: define foo first, then FooLike as the
> (unary) union of foo, then anotherfoo as a subclass of FooLike:
>
>   setClass("foo", representation(stuff="ANY"))
>   setClassUnion("FooLike", "foo")
>
>   showClass("FooLike")   # displays foo as the only known subclass
>
>   setClass("anotherfoo",
>       contains="FooLike",
>       representation(stuff="ANY")
>   )
>
>   showClass("FooLike")   # now displays foo and anotherfoo as
>                          # known subclasses
>
> The 3 ways lead to the same hierarchy. However the 3rd way is
> interesting because it allows one to define the FooLike virtual
> class as the parent of an existing foo class that s/he doesn't
> control.
>
>
Why not use setIs() for this? Everything then behaves as expected. I don't
think it makes much sense to "contain" a class union. Rather, you just want
to establish the inheritance relationship.


> For example, to define an ArrayLike class:
>
>   setClassUnion("ArrayLike", "array")
>   showClass("ArrayLike")  # displays array as a known subclass
>
> Note that ArrayLike is virtual with no slots (analog to a Java
> Interface), which is what is expected.
>
>   setClass("MyArrayLikeConcreteSubclass",
>       contains="ArrayLike",
>       representation(stuff="ANY")
>   )
>
>   showClass("MyArrayLikeConcreteSubclass")  # shows 2 slots!!
>
> What is the .Data slot doing here? I would expect to see that slot
> if MyArrayLikeConcreteSubclass was extending array but this is not
> the case here.
>
>   a <- new("MyArrayLikeConcreteSubclass")
>
>   is(a, "MyArrayLikeConcreteSubclass")  # TRUE  --> ok
>   is(a, "ArrayLike")                    # TRUE  --> ok
>   is(a, "array")                        # FALSE --> ok
>
> But:
>
>   is.array(a)  # TRUE --> not ok!
>
> Is is.array() confused by the presence of the .Data slot?
>
>
It looks like the unary union somehow equates ArrayLike and array and thus
makes ArrayLike confer a dim attribute (and thus is.array(a) returns TRUE).
Since S4 objects cannot have attributes that are not slots, it must do this
via a data part, thus the .Data slot.



> I can fix it by defining an "is.array" method for
> MyArrayLikeConcreteSubclass objects:
>
>   setMethod("is.array", "MyArrayLikeConcreteSubclass",
>       function(x) FALSE
>   )
>
> However, it feels that I shouldn't have to do this.
>
> Is the presence of the .Data slot in MyArrayLikeConcreteSubclass
> objects an unintended feature?
>
> Thanks,
> H.
>
> > sessionInfo()
> R Under development (unstable) (2016-01-07 r69884)
> Platform: x86_64-pc-linux-gnu (64-bit)
> Running under: Ubuntu 14.04.4 LTS
>
> locale:
>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
>  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
>  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8
>  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
>  [9] LC_ADDRESS=C               LC_TELEPHONE=C
> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
>
> attached base packages:
> [1] stats     graphics  grDevices utils     datasets  methods   base
>
> --
> Herv? Pag?s
>
> Program in Computational Biology
> Division of Public Health Sciences
> Fred Hutchinson Cancer Research Center
> 1100 Fairview Ave. N, M1-B514
> P.O. Box 19024
> Seattle, WA 98109-1024
>
> E-mail: hpages at fredhutch.org
> Phone:  (206) 667-5791
> Fax:    (206) 667-1319
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

	[[alternative HTML version deleted]]



[Rd] unary class union of an S3 class
Michael Lawrence