Skip to content
Back to formatted view

Raw Message

Message-ID: <B931F4BF-A66B-46F4-8D6E-B3D64FB507F4@R-project.org>
Date: 2021-01-28T08:41:12Z
From: Simon Urbanek
Subject: Unexpected behavior with inheritance and using S3 classes as slots in S4 class
In-Reply-To: <3NgorfmRHc0G3gBpmZfuMRSEcpfH6TwnVtcRctTA6Ze0ZYYOtgIzsYG0MekzBiWvSId53Cz1j2abdgJebaXo47kq7pK58pHQ-DrRIvJfhKc=@landtucker.com>

Ezra,

I think it's just the fact the you specified the wrong class inheritance in setOldClass() - it has to match you S3 definition, so it should be:

setOldClass(c("b","a"))

In which case it works:

> n(s1 = b_1)
An object of class "n"
Slot "s1":
[1] "world"
attr(,"class")
[1] "b" "a"

Cheers,
Simon



> On Jan 28, 2021, at 15:55, Ezra Tucker <ezra at landtucker.com> wrote:
> 
> Hi all,
> 
> I have a situation where I'm trying to use S3 classes as slots in an S4 class and am running into some problems with inheritance.
> 
> My example:
> ## with S3 classes
> a <- function(x) structure(x, class = "a")
> b <- function(x) structure(x, class = c("b", "a"))
> setOldClass(c("a", "b"))
> 
> a_1 <- a("hello")
> b_1 <- b("world")
> n <- setClass("n", slots = c(s1 = "a"))
> n(s1 = a_1) # works as expected
> is(b_1, "a") # yields TRUE
> n(s1 = b_1) # doesn't work-- unexpected
> 
> Error message is:
> Error in validObject(.Object) :
> invalid class ?n? object: invalid object for slot "s1" in class "n": got class "b", should be or extend class "a"
> 
> Digging in, validObject looks like it's calling getClassDef, which gives me
>> getClassDef("b")
> Virtual Class "b" [in ".GlobalEnv"]
> 
> Slots:
> 
> Name: .S3Class
> Class: character
> 
> Extends: "oldClass"
> 
> -- it extends "oldClass" but it doesn't extend class "a" despite the fact the S3 version does.
> 
> Now, In this simple example, I could have defined a and b as s4 classes, but in the real world, I didn't define them and have to use setOldClass.
> I'm currently getting around this issue by doing setClassUnion("ab", c("a", "b")) and then specify to use "ab" as the type for the slot, but since I already know b inherits from a, this ought not to be necessary (and there are other reasons this is undesirable).
> 
> 1. Is there anything I missed, in setting up this simple example, that would cause n(s1 = b_1) to work properly? Or is there anything I should do other than setClassUnion?
> 2. Is this a shortcoming of validObject or getClassDef?
> 
> Thank you all!
> -Ezra
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel