S4类中的R公共方法

时间:2013-01-19 23:27:11

标签: r oop class methods s4

我想继承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它有效,但是我真的必须定义一个泛型函数,虽然它只能用于这个对象吗?注释掉的部分可以工作,但是没有检查是否使用正确的参数调用了函数。这样做的正确方法是什么? 提前谢谢。

1 个答案:

答案 0 :(得分:2)

您想要使用方法分派,并且每个方法都需要与泛型相关联,所以是的,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