Dear Gabriel,

thank you so much for the scrutiny you took to look into this. Your explanation 
gives me a much better sense for what may be going on.

Admittedly, I still find it hard to understand why setAs() may have a side 
effect on inheritance. Looking at the documentation of setAs() again, this is 
an expected behaviour of setIs(), but not from setAs().

Maybe it makes sense to add a respective explicit explanation in the 
documentation of setAs()? For the time being, my personal take away is that I 
will try to circumvent setClassUnion() in combination with setAs().

Thanks again
Andreas

Von: Gabriel Becker <gabembec...@gmail.com>
Datum: Dienstag, 6. Oktober 2020 um 02:02
An: Blätte <andreas.blae...@uni-due.de>
Cc: Peter Dalgaard via R-devel <r-devel@r-project.org>
Betreff: Re: [Rd] S4 - inheritance changed by order of setClassUnion and setAs()

Andreas,

As far as I can tell (/conjecture), this is because the list of classes a 
particular class inherits from directly is appended to as needed, and so the 
order that a class extends others isd refined by the order that those 
connections are defined.

We can see this with two setClassUnion calls, rather than required setAs:


> setClass("grandma", slots = c(a = "character"))

> setClass("mother", slots = c(b = "matrix"), contains = "grandma")

> setClass("daughter", slots = c(c = "list"), contains = "mother")

> setClassUnion(name = "mr_x", members = c("daughter", "mother"))

> setClassUnion(name = "mr_y", members = c("daughter", "mother"))

> getClass("daughter")

Class "daughter" [in ".GlobalEnv"]



Slots:



Name:          c         b         a

Class:      list    matrix character



Extends:

Class "mother", directly

Class "mr_x", directly

Class "mr_y", directly

Class "grandma", by class "mother", distance 2

> setClass("grandma2", slots = c(a = "character"))

> setClass("mother2", slots = c(b = "matrix"), contains = "grandma2")

> setClass("daughter2", slots = c(c = "list"), contains = "mother2")

> setClassUnion(name = "mr_y2", members = c("daughter2", "mother2"))

> setClassUnion(name = "mr_x2", members = c("daughter2", "mother2"))

> getClass("daughter2")

Class "daughter2" [in ".GlobalEnv"]



Slots:



Name:          c         b         a

Class:      list    matrix character



Extends:

Class "mother2", directly

Class "mr_y2", directly

Class "mr_x2", directly

Class "grandma2", by class "mother2", distance 2


Note that mr_y2 appears in the list before mr_x2 the second block. The same 
thing is happening with setAs which (somewhat contrary to my expectations, 
admittedly) causes extends to consider "daughter" to inherit directly from 
"grandma" in your example (though it does note its via explicit coercion).


I think the take-away here is that when modifying the class inheritance 
structure explicitly, via setClassUnion or setAs (or, I assume, setIs) order 
inherently matters.

In fact order also matters for multiple inheritence via the normal contains 
mechanism. In practice, how could it not matter?


Multiple inheritence is very powerful but dangerous.



> setClass("person1", slots = c(f = "character"))

> setClass("person2", slots = c(g = "character"))

> setClass("people1", contains = c("person1", "person2"))

> getClass("people1")

Class "people1" [in ".GlobalEnv"]



Slots:



Name:          f         g

Class: character character



Extends: "person1", "person2"

> setClass("people2", contains = c("person2", "person1"))

> getClass("people2")

Class "people2" [in ".GlobalEnv"]



Slots:



Name:          g         f

Class: character character



Extends: "person2", "person1"

> setGeneric("ohno", function(obj) standardGeneric("ohno")

+ )

[1] "ohno"

> setMethod("ohno", "person1", function(obj) "person1!")

> setMethod("ohno", "person2", function(obj) "person2! Oh No!")

> ohno(new("people1"))

[1] "person1!"

> ohno(new("people2"))

[1] "person2! Oh No!"

Not sure if that helps any or not, but thats what I see here. And again, if I 
got anything wrong here, someone please correct me :)


Best,
~G

On Mon, Oct 5, 2020 at 1:47 PM Blätte, Andreas 
<andreas.blae...@uni-due.de<mailto:andreas.blae...@uni-due.de>> wrote:
Dear colleagues,

there is a behaviour with S4 (virtual) classes that I find  very hard to 
understand: Depending on the position
of setAs(), the tree of inheritance changes.

This is my baseline example that defines the classes "grandma", "mother", 
"daughter" and a virtual
class "mr_x". For a new instance if "daughter", "mr_x" is betweeen "mother" and 
"grandma".

setClass("grandma", slots = c(a = "character"))
setClass("mother", slots = c(b = "matrix"), contains = "grandma")
setClass("daughter", slots = c(c = "list"), contains = "mother")
setClassUnion(name = "mr_x", members = c("daughter", "mother"))
setAs(from = "daughter", to = "grandma", def = function(from) new("grandma"))
is(new("daughter"))

[1] "daughter" "mother"   "mr_x"     "grandma"

Yet if I change the order of setAs() and setClassUnion(), this alters the 
pattern of inheritance.

setClass("grandma", slots = c(a = "character"))
setClass("mother", slots = c(b = "matrix"), contains = "grandma")
setClass("daughter", slots = c(c = "list"), contains = "mother")
setAs(from = "daughter", to = "grandma", def = function(from) new("grandma"))
setClassUnion(name = "mr_x", members = c("daughter", "mother"))
is(new("daughter"))

[1] "daughter" "mother"   "grandma"  "mr_x"

Is there a reasonable explanation for this behavior? I could not find any and I 
would appreciate
your help. If it is not an unintended behavior, I find it very confusing and 
hard to anticipate.

Kind regads
Andreas

--
Prof. Dr. Andreas Blätte
Professor of Public Policy and Regional Politics
University of Duisburg-Essen

        [[alternative HTML version deleted]]

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

        [[alternative HTML version deleted]]

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

Reply via email to