On 03/18/2016 03:28 PM, Michael Lawrence wrote:

On Fri, Mar 18, 2016 at 2:53 PM, Hervé Pagès <hpa...@fredhutch.org
<mailto:hpa...@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?

  > setClass("ArrayLike")
  > setIs("array", "ArrayLike")
  Error in setIs("array", "ArrayLike") :
class “array” is sealed; new superclasses can not be defined, except by 'setClassUnion'

How do you define a virtual class as the parent of an existing class
with setIs?

Everything then behaves as expected. I
don't think it makes much sense to "contain" a class union.

Why is that? A class union is just a virtual class with no slot
that is the parent of the classes that are in the union. All the
classes in the union contain their parent. What's interesting is that
this union is actually open to new members: when I later define a new
class that contains the class union, I'm just adding a new member to
the union.

Rather, you
just want to establish the inheritance relationship.

Isn't what I'm doing when I define a new class that contains the
class union?


    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

Clearly the unary union makes ArrayLike a parent of array, as it should
be. This can be confirmed by extends():

  > extends("array", "ArrayLike")
  [1] TRUE
  > extends("ArrayLike", "array")
  [1] FALSE

The results for is(a, "ArrayLike") (TRUE) and is(a, "array") (FALSE)
on a MyArrayLikeConcreteSubclass instance are consistent with this.

So the little 3-class hierarchy I end up with in the above example
is exactly how expected:

         ArrayLike
          ^    ^
          |    |
      array    MyArrayLikeConcreteSubclass

What is not expected is that MyArrayLikeConcreteSubclass has a .Data
slot and that is.array(a) returns TRUE on a MyArrayLikeConcreteSubclass
object.

H.

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: hpa...@fredhutch.org <mailto:hpa...@fredhutch.org>
    Phone: (206) 667-5791 <tel:%28206%29%20667-5791>
    Fax: (206) 667-1319 <tel:%28206%29%20667-1319>

    ______________________________________________
    R-devel@r-project.org <mailto:R-devel@r-project.org> mailing list
    https://stat.ethz.ch/mailman/listinfo/r-devel



--
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: hpa...@fredhutch.org
Phone:  (206) 667-5791
Fax:    (206) 667-1319

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to