如何使用方法(无需输入值)在S4对象R中设置值



这是两个部分问题。我想基于不同的插槽值设置原型S4对象的值,或者我想将其作为一种方法实现。

我有一个我要创建的对象。它有一些插槽。我想根据从另一个插槽中提出的值设置一个插槽值。这是我想做的简化版本。

即,

setClass("Person",
    representation(name = "character", age = "numeric", doubleAge = "numeric"),
    prototype(name = "Bob", age = 5, doubleAge = 10) )

现在,我想创建一个对象,但根据年龄段设置双重安装值。

p1 <- new("Person", name = "Alice", age = 6)

我看到

An object of class "Person"                                                                                                      
Slot "name":                                                                                                                     
[1] "Alice"                                                                                                                  
Slot "age":                                                                                                                    
[1] 6                                                                                                                        
Slot "doubleAge":                                                                                                              
[1] 10       

,但我想看到doubleeage是12.在原型中,我不知道如何将doubleAge = 10更改为doubleAge = 2*age

之类的东西

因此,作为一种解决方案,我尝试制作设置函数init,该函数在创建后设置值。这是第2部分问题。

setGeneric("init", "Person", function(object) {
    standardGeneric("init")
}
setMethod("init","Person", function(object) {
    object@doubleAge <- object@age*2
    object
}

如果我在返回12的方法中打印 object@doubleAge,但是范围似乎结束了,因为它返回

时是10

目前的工作非常相似,但不正确。

setGeneric("init<-", "Person", function(object) {
    standardGeneric("init<-")
}
setMethod("init<-","Person", function(object) {
    object@doubleAge <- object@age*2
    object
}

,但是我必须像init(p1) <- NULL一样打电话,这似乎很奇怪。我知道这个示例似乎很容易,但这只是一个更复杂的现实世界问题的准则示例。

似乎对我有用的初始化方法覆盖。例如

setClass("Person",
         representation(name = "character", age = "numeric", doubleAge = "numeric"),
         prototype(name = "Bob", age = 5, doubleAge = 10) )
setMethod("initialize", "Person", function(.Object, ...) {
  .Object <- callNextMethod()
  .Object@doubleAge <- .Object@age*2
  .Object
})
(p1 <- new("Person", name = "Alice", age = 6))
# An object of class "Person"
# Slot "name":
# [1] "Alice"
# Slot "age":
# [1] 6
# Slot "doubleAge":
# [1] 12

callNextMethod()运行"默认"初始化器,以设置我们不混乱的所有值。然后,我们只是更改所需的值并返回更新的对象。

除了上述initialize方法外,您可能还需要为@<-设置一种方法。原因是如果您做

之类的事情
x <- new("person", age=5)

然后,您有一个有效的人,有age=5doubleage=10。但是,如果您现在做

x@age <- 6

?现在age为6,但doubleage仍然是10,因此该对象不再有效。

R文档声称您可以为@<-编写一种方法,该方法将解决此问题:

setMethod("@<-",signature(object="Person"),function(object,name,value){
  if(name=="age"){
    object@age <- x
    object@doubleAge <- x*2
  } else if(e2=="doubleAge"){
    object@doubleAge <- x
    object@age <- value/2
  } else slot(object,name) <- value
  object
})

但是,当您实际运行以上时,您会收到一个错误:

setGeneric中的错误(f,where = where):‘@&lt; - ’派遣 内部;可以定义方法,但是通用函数是 隐式,不能更改。

这是一个奇怪的错误,因为我们不是要重新定义通用性。实际上,我们发现,当我们尝试

method.skeleton("@<-",signature(object="Person"))

r勉强告诉我们

genericforbasic中的错误(名称):可能无法定义方法 原始函数'@&lt; - ’在此版本的r

因此,如果您想可靠地让插槽保持一致,我们将不得不按照

的方式编写自己的Getters和Setter
setAge <- function(x,value){
  x@age <- value
  x@doubleAge <- value*2
  x
}

最新更新