From mtmorgan at fhcrc.org  Tue Sep 15 15:23:55 2009
From: mtmorgan at fhcrc.org (Martin Morgan)
Date: Tue, 15 Sep 2009 06:23:55 -0700
Subject: [Rd] S3 objects in S4 slots
In-Reply-To: <116117690909150300v4a703807se7b08b94c3f1a68d@mail.gmail.com>
References: <116117690909150300v4a703807se7b08b94c3f1a68d@mail.gmail.com>
Message-ID: <4AAF956B.7090704@fhcrc.org>

Hi Martin Kober --

Martin Kober wrote:
> Hello,
> 
> I am the maintainer of the stringkernels package and have come across
> a problem with using S3 objects in my S4 classes.
> 
> Specifically, I have an S4 class with a slot that takes a text corpus
> as a list of character vectors. tm (version 0.5) saves corpora as
> lists with a class attribute of c("VCorpus", "Corpus", "list"). I
> don't actually need the class-specific attributes, I only care about
> the list itself.
> 
> Here's a simplified example of my problem:
> 
>> setClass("testclass", representation(slot="list"))
> [1] "testclass"
>> a = list(a="1", b="2")
>> class(a) = c("VCorpus", "Corpus", "list") # same as corpora in tm v0.5

This has the feel of a workaround, but

setOldClass(class(a)[1:2]); setIs("Corpus", "list")

helps here, first registering c('vCorpus', 'Corpus') as an S3 hierarchy
and then defining the relationship between the root of the hierarchy and
(the S4 class) 'list'.

Martin (Morgan)

>> x = new("testclass", slot=a)
> Error in validObject(.Object) :
>   invalid class "testclass" object: 1: invalid object for slot "slot"
> in class "testclass": got class "VCorpus", should be or extend class
> "list"
> invalid class "testclass" object: 2: invalid object for slot "slot" in
> class "testclass": got class "Corpus", should be or extend class
> "list"
> invalid class "testclass" object: 3: invalid object for slot "slot" in
> class "testclass": got class "list", should be or extend class "list"
> 
> The last line is a bit confusing here (``got class "list", should be
> or extend class "list"''). There's an even more confusing error
> message when I try to assign the slot later on:
> 
>> y = new("testclass")
>> y at slot = a
> Error in checkSlotAssignment(object, name, value) :
>   c("assignment of an object of class \"VCorpus\" is not valid for
> slot \"slot\" in an object of class \"testclass\"; is(value, \"list\")
> is not TRUE", "assignment of an object of class \"Corpus\" is not
> valid for slot \"slot\" in an object of class \"testclass\"; is(value,
> \"list\") is not TRUE", "assignment of an object of class \"list\" is
> not valid for slot \"slot\" in an object of class \"testclass\";
> is(value, \"list\") is not TRUE")
> 
> The last part of the message claims that ``is(value, "list") is not
> TRUE'', but is(a, "list") is certainly TRUE. (??)
> 
> On a side note, it does work when "list" is the first entry in class().
> 
> 
> I tried to use setOldClass, but seemingly using list is not possible
> because it does not extend oldClass, or I didn't find out how to do
> it:
>> setOldClass(c("VCorpus", "Corpus", "list"))
> Error in setOldClass(c("VCorpus", "Corpus", "list")) :
>   inconsistent old-style class information for "list"; the class is
> defined but does not extend "oldClass"
> 
> 
> Intuitively I would have thought that, because the underlying data is
> of type list, it would "fit" into an object slot requiring a list,
> irrespective of S3 class attributes. The only thing I can think of is
> a manual solution removing the class attribute.
> 
> Is there a way to define lists with S3 class attributes such that they
> are accepted as lists in S4 object slots? Or any other ways to solve
> this?
> 
> 
> Thanks in advance
> Best Regards
> Martin
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



[Rd] S3 objects in S4 slots
Martin Morgan