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
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...@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?