【问题标题】:R public method in S4 classS4类中的R公共方法
【发布时间】:2013-01-03 09:48:25
【问题描述】:

我想继承一个 S4 类并向该子类添加一个特殊方法。 该方法应该只适用于子类,它对我的​​应用程序中的任何其他类都没有意义。

    setClass("MySpecies", contains="Species", ##Species is an S4 class
         representation(x="numeric"))

setMethod("initialize", "MySpecies", function(.Object, x, ...){
  .Object@x <- x
  args <- list(...)
  for(i in seq_len(length(args))){
    attr(.Object, names(args)[i]) <- args[[i]]
  }
  .Object
})

##CalcMatrix <- function(.Object, y){
##  x <- .Object@x
##  matrix(x, x*2, y*3)
##}

setGeneric("CalcMatrix", function(object, y){standardGeneric("CalcMatrix")})
setMethod("CalcMatrix", "MySpecies",function(object, y){
  x <- object@x
  matrix(x, x*2, y*3)
})

使用setGeneric 它可以工作,但我真的必须定义一个通用函数,尽管它只用于这个对象吗?注释掉的部分有效,但是没有检查是否使用正确的参数调用函数。这样做的正确方法是什么? 提前致谢。

【问题讨论】:

  • 在 S4 中,方法属于函数,而不是类。一旦你明白了这一点,你就可以更轻松地使用 S4。

标签: r oop class methods s4


【解决方案1】:

您想要使用方法分派,并且每个方法都需要与泛型关联,所以是的,setGeneric 是必需的。

还有一点不请自来的建议......使用正式的类系统(大概是因为定义明确的类有助于编写更复杂的程序)然后通过添加任意属性来颠覆结构有点奇怪;这些确实应该是您班级中额外的、定义明确的插槽。

让我们通过定义 Species 来使您的示例可重现

setClass("Species", representation(y="numeric"))
setClass("MySpecies", contains="Species", ##Species is an S4 class
         representation(x="numeric"))

对 S4 类的一个隐含要求是 new("MySpecies") 有效;您的 initialize 方法未通过此测试(因为 x 没有默认值)。此外,通常的做法是期望初始化MySpecies 调用它包含的类的initialize 方法。可以写

setMethod("initialize", "MySpecies", function(.Object, ..., x=numeric()) {
    callNextMethod(.Object, x=x, ...)
})

注意callNextMethod,以便正确初始化基类。使用... 并将其传递给callNextMethod 意味着可能在Species 中定义的插槽也将被正确初始化。此外,x 需要在... 之后,因为initialize 被定义为采用代表包含类的未命名参数——new("MySpecies", new("Species")) 需要工作,即使它是一种构造参数的方式,你不这样做直接使用。上面的initialize 方法实际上除了默认的初始化方法之外没有做任何其他事情,所以实际上(通常是这种情况)根本不编写初始化方法是有意义的。

然后在最近的 R 中,setClass 返回一个默认构造函数,所以

MySpecies <- setClass("MySpecies", contains="Species", ##Species is an S4 class
                      representation(x="numeric"))

然后

> MySpecies(x=1:5, y=5:1)
An object of class "MySpecies"
Slot "x":
[1] 1 2 3 4 5

Slot "y":
[1] 5 4 3 2 1

【讨论】:

  • 您好,感谢您的快速回答。在我的程序中,我扩展了一个现有的类来专门化它,所以它还有两个我想在我的方法中访问的属性,所以在这种情况下,看起来通用函数是最好的。感谢callNextMethod 的提示,我以前不知道。默认构造函数对我不起作用,我收到一个错误:错误:找不到函数“MySpecies”。我正在运行 R 2.14.1。是否仅在较新版本中可用?
  • 只需在类定义中创建属性槽,而不是以特别的方式附加它们。我认为,构造函数是在当前版本 R-2.15 中引入的。
  • 默认的初始化方法适用于我所有的子类,我可以去掉很多冗余代码!
猜你喜欢
  • 2018-09-27
  • 2012-06-19
  • 2015-12-17
  • 2021-02-17
  • 2015-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多