我有一个超类fb
的类层次结构,其中不存在任何对象(我尝试过虚拟类但遇到了无法从虚拟类初始化对象的问题)。此外,我有两个具有相同插槽的子类(foo
,bar
)。现在我想创建一个新对象,对超类使用initialize方法,该超类基于某个值返回其中一个子类的对象:
setClass("fb", representation( x = "numeric"))
setClass("foo", contains = "fb")
setClass("bar", contains = "fb")
setMethod("initialize", "fb", function(.Object, x) {
if (x < 5) class(.Object) <- "foo"
else class(.Object) <- "bar"
.Object@x <- x
.Object
})
> new("fb", x = 3)
Error in initialize(value, ...) :
initialize method returned an object of class "foo" instead of the required class "fb"
显然(并且可能有充分的理由)R不允许这样做。有没有办法在方法中实现我想要的东西而在创建新对象时不使用if-else构造?
答案 0 :(得分:4)
fb
课程应该是虚拟的,您的initialize
方法不应更改.Object
的课程。您可以编写一个函数fb
来执行条件实例化。
setClass("fb", representation( x = "numeric", "VIRTUAL"))
setClass("foo", contains = "fb")
setClass("bar", contains = "fb")
fb <-
function(x)
{
if (x < 5) new("foo", x=x)
else new("bar", x=x)
}
fb
是一个构造函数,对用户来说更方便,并将接口与类层次结构与其实现分开,这通常被视为一件好事。
对于值得对S4 initialize
方法进行隐式约束的是new("foo")
(使用类名称调用new
但没有其他参数)必须工作(否则会出现故障)你试图扩展foo)。所以初始化方法的范例是
setMethod(initialize, "foo", function(.Object, ..., x=1) {
.Object <- callNextMethod(.Object, ...)
.Object@x <- x
.Object
})
虽然经常(在这种情况下,initialize
正在进行插槽分配),根本不需要初始化方法。请注意...
的使用,x
的定位(要求在对new
的相应调用中命名参数)以及使用默认值。