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