当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


R setOldClass 注册旧式 (S3) 类和继承


R语言 setOldClass 位于 methods 包(package)。

说明

将old-style(又名“S3”)类注册为正式定义的类。简单的用法将采用以下形式:

setOldClass(Classes)

其中 Classes 是字符向量,它是 S3 对象的 class 属性。在包的代码中调用 setOldClass() 允许将该类用作正式 (S4) 类和方法签名中的槽(请参阅 Methods_for_S3 )。正式类还可以包含已注册的 S3 类(有关详细信息,请参阅S3Part)。

如果 S3 类具有一组已知的属性,则可以通过调用 setOldClass() 中的 S4Class= 指定等效的 S4 类;请参阅“Known Attributes”部分。

用法

setOldClass(Classes, prototype, where, test = FALSE, S4Class)

参数

Classes

一个字符向量,给出 S3 类的名称,它们将出现在 S3 计算中 class 属性赋值的右侧。

除了 S3 类之外,如果已知 S3 类要求其数据采用该形式,则还可以指定对象类型或其他有效数据部分。

S4Class

(可选)S4 类的类定义或类名称。新类将具有该类的所有槽和其他属性,以及 Classes 参数中多个名称隐含的任何 S3 继承。请参阅下面的“具有已知属性的 S3 类”部分。

prototype, where, test

这些参数目前是允许的,但在典型应用中不推荐。

prototype :用作原型的可选对象。如果 S3 类不是VIRTUAL(默认),则优先使用S4Class=

where :存储类定义的位置。应该是应用程序包中正常使用的默认值(包命名空间)。

test :标志,如果是 TRUE ,则安排显式测试每个对象的继承,如果 S3 类可以有一组不同的类字符串,并且具有相同的第一个字符串,则需要。这样的类本质上是畸形的,而且很少见,应该避免。

细节

Classes 中的名称(或每个名称)将被定义为 S4 类,扩展类 oldClass ,它是所有 old-style 类的 ‘root’ 。其类属性中具有多个名称的 S3 类将具有与正式类相应的继承。请参阅"mlm" 示例。

S3 类没有正式定义,因此也没有正式定义的槽。如果没有提供 S4 类作为模型,则创建的类将是虚拟类。如果虚拟类(任何虚拟类)用于另一个类中的槽,则该类的初始化方法需要在该槽中放置合法的内容;否则它将被设置为 NULL

有关混合 S3 和 S4 方法的方法分派和继承的详细信息,请参阅Methods_for_S3

某些 S3 类不能表示为 S4 类和超类的普通组合,因为类属性中具有相同初始字符串的对象可以有不同的字符串。幸运的是,这样的课程很少见。它们违反了面向对象编程的基本思想,应该避免。如果您必须处理它们,仍然可以将此类类注册为 S4 类,但现在必须验证每个对象的继承,并且您必须使用参数 test=TRUE 调用 setOldClass

预定义的旧类

标准 R 发行版中许多广泛使用的 S3 类都是预先定义的,可与 S4 一起使用。这些不需要在包中显式声明(尽管这样做没有什么坏处)。

列表.OldClassesList 包含由方法包定义的old-style 类。列表的每个元素都是一个字符向量,如果包含继承,则具有多个字符串。创建methods包时,列表中的每个元素都被传递给setOldClass;因此,这些类可以在 setMethod 调用中使用,并具有列表所暗示的继承。

具有已知属性的 S3 类

如果保证 S3 类具有已知类的某些属性(其中与槽一样,“known” 表示该属性是指定类的对象或该类的子类),则可以对 S3 类进行进一步规范。 。

在这种情况下,对setOldClass()的调用可以提供表示已知结构的S4类定义。由于 S4 槽被实现为属性(很大程度上正是出于这个原因),因此可以在 S4 类的表示中指定已知属性。通常的技术是创建具有所需结构的 S4 类,然后提供类名称或定义作为参数 S4Class=setOldClass()

请参阅下面示例中的类 "ts" 的定义以及参考文献第 10.2 节中的 data.frame 示例。对 setClass 的调用来创建 S4 类可以使用相同的类名,如此处所示,只要对 setOldClass 的调用位于同一包中即可。为了清楚起见,它应该是同一文件中的下一个表达式。

在示例中,我们定义"ts"作为带有数字槽的向量结构"tsp"。该定义的有效性依赖于该类的所有 S3 代码都与该定义一致的断言;具体来说,所有"ts"对象将表现为向量结构并且将具有数字"tsp"属性。我们相信这对于所有基本代码都是如此R,但与 S3 类一样,无法保证。

如果断言 S3 类的行为与虚拟超类一致(在示例中,断言时间序列对象与 structure 类一致),则 S4 类定义可以具有虚拟超类(如 "ts" 情况)。

S3 类未能实现其断言行为通常不会得到纠正,因为 S3 类本质上没有定义,并且由此产生的无效 S4 对象可能会导致各种痛苦。许多 S3 类不是已知槽的候选者,或者是因为无法保证属性的存在或类(例如,数组中的 dimnames,尽管这些甚至不是 S3 类),或者是因为该类使用列表的命名组件而不是属性(例如 "lm" )。有时丢失的属性不能表示为槽,甚至不能假装它与类 "NULL" 一起存在,因为与槽不同,属性不能具有值 NULL

然而,通常可以容忍的一种不规则行为是有选择地向那些保证存在的属性添加其他属性(例如, model.frame 返回的 "data.frame" 对象中的 "terms" )。 validObject 的有效性检查忽略额外属性;即使将来加强此检查,扩展 S3 类的类也可能会被免除,因为额外的属性非常常见。

例子



require(stats)

## "lm" and "mlm" are predefined; if they were not this would do it:
## Not run: 
setOldClass(c("mlm", "lm"))
## End(Not run)

## Define a new generic function to compute the residual degrees of freedom
setGeneric("dfResidual",
  function(model) stop(gettextf(
    "This function only works for fitted model objects, not class %s",
                                class(model))))

setMethod("dfResidual", "lm", function(model)model$df.residual)

## dfResidual will work on mlm objects as well as lm objects
myData <- data.frame(time = 1:10, y = (1:10)^.5)
myLm <- lm(cbind(y, y^3)  ~ time, myData)



## two examples extending S3 class "lm": class "xlm" directly
## and "ylm" indirectly
setClass("xlm", slots = c(eps = "numeric"), contains = "lm")
setClass("ylm", slots = c(header = "character"), contains = "xlm")
ym1 = new("ylm", myLm, header = "Example", eps = 0.)
## for more examples, see ?\link{S3Class}.




## Not run: 
## The code in R that defines "ts" as an S4 class
setClass("ts", contains = "structure", slots = c(tsp = "numeric"),
         prototype(NA, tsp = rep(1,3)))
       # prototype to be a legal S3 time-series
## and now registers it as an S3 class
setOldClass("ts", S4Class = "ts", where = envir)

## End(Not run)

参考

Chambers, John M. (2016) Extending R, Chapman & Hall. (Chapters 9 and 10, particularly Section 10.8)

也可以看看

setClass , setMethod

相关用法


注:本文由纯净天空筛选整理自R-devel大神的英文原创作品 Register Old-Style (S3) Classes and Inheritance。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。