Skip to content

Inheriting from factors + co.

5 messages · Uwe Ligges, Torsten Steuernagel

#
I'm trying to create a formal class that does the following:

1) accept objects of arbitrary class as .Data slot

2) provide a set of other slots that are of fixed type (as usual)

The following two approaches came to my mind:

A)

setClass("myclass", representation("ANY", x = "numeric", y 
="numeric"))

new("myclass", 1:10)		# works 
new("myclass", "Test")		# works
new("myclass", factor(1:10))	# fails

While I'm able to specify any object that has a formal class as data part 
it won't work with factors or other non-formal classes.

B)

Since it is sufficient to use anything that inherits from "vector" and 
"factor", I also tried the following one which seems to be cleaner than 
using "ANY" directly.

setClassUnion("myunion", representation("vector", "factor"))	# 
works
setClass("myclass", representation("myunion", x="numeric", 
y="numeric"))

new("myclass", 1:10)		# fails

Now it isn't possible to assign anything as data part at all, as long as 
the union contains any non-formal classes such as "factor". Replacing 
"factor" with a formal class will do, of course.

I wonder if there is some way that does the trick because other 
approaches aren't very straightforward. The obvious solution would be 
a list as .Data part which can store anything but that isn't easy to 
maintain. My goal is to have a formal class whose objects (i.e. .Data 
part) can either be anything derived from "vector" or a factor (ordered). 
I already played around with setIs() for implicit coercion but that doesn't 
do anything as long as one of the classes is an S3 class.

Thanks for your help,

Torsten
#
Torsten Steuernagel wrote:
Why do you think it fails?

It works perfectly for me with R-1.8.1 for Windows.
You haven't told anything about your R version, I suspect your are using
an outdated one.

Uwe Ligges
#
On 24 Feb 2004 at 21:38, Uwe Ligges wrote:

            
I was typing faster than thinking. It doesn't actually fail but what I get is 
a numeric vector with a levels attribute. If I specify a factor as .Data 
part I expect that the created object IS a factor and 
is.factor(new("myclass", factor(1:10))) returns TRUE.
Sorry, forgot that one. I'm also using R 1.8.1 on Windows.

Thanks,

Torsten
#
Torsten Steuernagel wrote:

            
So you are going to handle/mix the S4 class like/with S3 classes?
Hmm. It can be either of class "myclass" or of class "factor".
I'd define a separate explicit slot for such a class:

   setClass("myclass", representation(mainSlot = "ANY",
       x = "numeric", y = "numeric"))

John Chambers might want to correct me...

Uwe
#
On 25 Feb 2004 at 10:00, Uwe Ligges wrote:

            
Yes, and there is the problem. With S4 classes, it works. Now I would 
expect that is(factor(S3object, "ANY") will be FALSE for factor and any 
other S3 class, but is(S3object, "ANY") always gives TRUE.
It is of class "myclass" but it should inherit from "factor" by the .Data 
part if I specify a factor. That's what it does with S4 classes:

my1 <- new("myclass", 1:10)
class(my1)			#  "myclass"
is.numeric(my1)		# TRUE

my2 <- new("myclass", "abc")
class(my2)			#  "myclass"
is.character(my2)		# TRUE

In those cases the object actually is a numeric or a character and thus 
can be treated accordingly.
That works, of course. But that's not what I'm looking for. This requires 
using the slot explicitly (not impossible, but I'd really prefer to have it in 
the .Data part). One main drawback is that R just doesn't accept S3 
classes as .Data part:

setClass("myclass", representation("factor"))

It creates a new class (although a warning is issued) and also extends 
from "factor" but doesn't create the .Data slot. That's also the reason 
why my second approach with setClassUnion() doesn't work as soon as 
an S3 class is part of the union. I just don't understand why S3 classes 
in explicit slots work perfectly well whereas it seems impossible to have 
them in the .Data slot. 

Torsten