blob: 44d877fd647c8c554e13672ffffeb587288d7387 [file] [log] [blame]
# File src/library/methods/R/ClassUnion.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1995-2012 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available at
# https://www.R-project.org/Licenses/
.InitClassUnion <- function(where) {
setClass("ClassUnionRepresentation", "classRepresentation",
validity =function(object) {
if(isTRUE(object@virtual) && length(object@slots)==0 &&
is.null(object@prototype))
TRUE
else
"Class must be an empty virtual class with NULL prototype"
}, where = where)
## some classes in methods package are unions--now they can be officially
setClassUnion("OptionalFunction", c("function", "NULL"), where)
setClassUnion("PossibleMethod", c("function", "MethodDefinition"), where)
clList <- c("ClassUnionRepresentation", "OptionalFunction",
"PossibleMethod")
assign(".SealedClasses", c(get(".SealedClasses", where), clList), where)
}
setClassUnion <- function(name, members = character(), where = topenv(parent.frame())) {
if(length(members)>0) {
membersDefined <- sapply(members, isClass, where = as.environment(where))
if(!all(membersDefined))
stop(gettextf("the member classes must be defined: not true of %s",
paste(.dQ(as(members[!membersDefined], "character")), collapse=", ")), domain = NA)
}
def <- new("ClassUnionRepresentation",
makeClassRepresentation(name, package = getPackageName(where), where = where))
prev <- getClassDef(name, where = where)
value <- setClass(name, def, where = where)
failed <- character()
## the prototype of the union will be from the first non-virtual
## subclass, except that we prefer NULL if "NULL" is a subclass
hasNull <- match("NULL", members, 0)
if(hasNull)
members <- c("NULL", members[-hasNull])
for(what in members) {
if(is(try(setIs(what, name, where = where)), "try-error")) {
if(!is.character(what))
what <- getClass(what, TRUE, where)@className
failed <- c(failed, what)
}
}
if(length(failed)>0) {
if(is.null(prev))
try(removeClass(name, where = where))
else
try(setClass(name, prev, where = where))
stop(gettextf("unable to create union class: could not set members %s",
paste(.dQ(failed), collapse=", ")), domain = NA)
}
invisible(value)
}
isClassUnion <- function(Class) {
## test the class DEFINITION for representing a union
if(is.character(Class))
Class <- getClass(Class, TRUE) # the real def. or a dummy
extends(class(Class), "ClassUnionRepresentation")
}