Let's start from a simpler description, because the use of
"sealed"
adds some confusion. Here's a basic version. I have two packages, P2
and P3, with different definitions of "myClass".
Classes with the same name on two packages are supposed to work, at
least for generating objects. There is a bug (see below) and a
workaround, but with or without the workaround you need to apply new()
to a class _object_, not just a name, if you want to generate objects in
the global environment.
Here's what currently works, using the workaround:
> c2 = get(classMetaName("myClass"), envir =
asNamespace("P2"))
> c3 = get(classMetaName("myClass"), envir =
asNamespace("P3"))
> x2 = new(c2)
> x3 = new(c3)
> class(x2)
[1] "myClass"
attr(,"package")
[1] "P2"
> class(x3)
[1] "myClass"
attr(,"package")
[1] "P3"
By using asNamespace(), it's not necessary to export the class
definitions, and possibly better not to.
Two comments:
- The bug is that you should be able to use
c2 = getClass("myClass", asNamespace("P2"))
instead of the call to get(). But a current misuse of cached
definitions means that only the first definition is known. Hence the
need for a workaround using classMetaName() to get the class definition
directly. I think the fix is easy & will try to add it to r-devel
fairly soon.
- There are limitations to using duplicated class names, because not all
computations will carry the appropriate package information to say which
"myClass" we mean. So if one can avoid duplicating class names, life
will be easier, and I suspect that duplicated classes that are _not_
exported will work better, because computations will be forced into the
individual namespaces with less chance for getting the wrong definition.
Martin Morgan wrote:> I'd like to have two packages with S4 classes with the same name but
> different implementation. To that end I create a package tmpA with
>
> setClass("A",
> representation=representation(
> x="numeric"),
> sealed=TRUE)
> setClass("B",
> representation=representation(
> x="numeric"))
> B <- function(...) new("B", ...)
>
> and a NAMESPACE having only
>
> import(methods)
> export(B)
>
> I duplicate this package source directory structure, renaming the
> duplicate package tmpB in its Description file. After R CMD
> INSTALL'ing both, I
>
>
>> library(tmpA)
>> library(tmpB)
>>
> Error in setClass("A", representation = representation(x =
"numeric"), :
> "A" has a sealed class definition and cannot be redefined
> Error : unable to load R code in package 'tmpB'
> Error: package/namespace load failed for 'tmpB'
>
>> setClass("A", prototype(y="numeric"))
>>
> Error in setClass("A", c(y = "numeric")) :
> "A" has a sealed class definition and cannot be redefined
>
> It appears that, although 'where' in setClass influences the
location
> of the class definition, there is a global class table that means only
> one class of a particular name can ever be defined. Is that the
> intended behavior?
>
> If I create a class B in the global environment
>
>
>> setClass("B", representation(y="numeric"))
>>
> [1] "B"
>
> and then use the constructor from tmpA, I end up with an instance of
> the globally defined class B, rather than the one defined in the
> constructor's name space:
>
>
>> B()
>>
> An object of class "B"
> Slot "y":
> numeric(0)
>
> How would I write B to return an instance of B as defined in tmpA?
>
> Thanks,
>
> Martin
>
>
>> sessionInfo()
>>
> R version 2.7.0 Under development (unstable) (2008-02-09 r44397)
> x86_64-unknown-linux-gnu
>
> locale:
>
LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_MESSAGES=en_US.UTF-8;LC_PAPER=en_US.UTF-8;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=en_US.UTF-8;LC_IDENTIFICATION=C
>
> attached base packages:
> [1] stats graphics grDevices datasets utils methods base
>
> other attached packages:
> [1] tmpA_1.0
>
>
[[alternative HTML version deleted]]