S7
S7 包是一个新的 OOP 系统,旨在作为 S3 和 S4 的继任者。它由 R Consortium 面向对象编程工作组协作设计和实现,该工作组包括 来自 R-Core、Bioconductor、tidyverse/Posit 以及 更广泛的 R 社区的代表。
S7 具有一定的实验性质;我们对设计很有信心,但目前它在实际 使用中相对较少。我们希望避免任何 重大破坏性更改,但如果发现重大 问题,我们保留更改的权利。
安装
该项目的长期目标是将 S7 合并到 base R 中。目前, 你可以通过从 CRAN 安装它来进行实验:
install.packages("S7")
用法
本节对 S7 的整体内容进行了非常简要的概述。有关基本知识的更多信息,请参阅 vignette("S7");有关泛型和方法的信息,请参阅
vignette("generics-methods");有关类和对象的信息,请参阅
vignette("classes-objects");有关与 S3 和 S4 兼容性的信息,请参阅
vignette("compatibility")。
library(S7)
类与对象
S7 类具有形式化定义,其中包括一个属性列表
和一个可选的验证器。使用 new_class() 来定义一个类,其中
:= 运算符从你为其分配结果的变量中提供其名称:
Range := new_class(
properties = list(
start = class_double,
end = class_double
),
validator = function(self) {
if (length(self@start) != 1) {
"@start must be length 1"
} else if (length(self@end) != 1) {
"@end must be length 1"
} else if (self@end < self@start) {
"@end must be greater than or equal to @start"
}
}
)
new_class() 返回类对象,该对象也是用于创建类实例的构造函数:
x <- Range(start = 1, end = 10)
x
#> <Range>
#> @ start: num 1
#> @ end : num 10
属性
对象所具有的数据称为其属性。使用 @ 来
获取和设置属性:
x@start
#> [1] 1
x@end <- 20
x
#> <Range>
#> @ start: num 1
#> @ end : num 20
属性会根据在
new_class()(在本例中为 double)中声明的类型,以及 validator 类进行自动验证:
x@end <- "x"
#> Error in `<Range>@end`:
#> ! <Range>@end must be <double>, not <character>
x@end <- -1
#> Error:
#> ! <Range> object is invalid:
#> - @end must be greater than or equal to @start
泛型与方法
与 S3 和 S4 类似,S7 采用函数式 OOP,其中方法属于泛型函数,方法调用看起来与其他函数调用无异:generic(object, arg2, arg3)。这种风格被称为函数式,因为从外部看它像是一个普通的函数调用,且内部组件也是函数。
使用 new_generic() 创建一个新的泛型:它需要泛型的名称(同样通过 := 提供,并用于错误消息)以及用于分派的参数。可选的 fun 参数提供泛型的主体。仅当你的泛型具有未用于方法分派的额外参数时,才需要此参数。
inside := new_generic("x")
一旦你拥有了一个泛型,你就可以使用 method<- 为特定类定义一个方法
# Add a method for our class
method(inside, Range) <- function(x, y) {
y >= x@start & y <= x@end
}
inside(x, c(0, 5, 10, 15))
#> [1] FALSE TRUE TRUE TRUE
您可以使用 method<- 在 S7 泛型上为基本类型注册方法,以及在 S3 或 S4 泛型上注册 S7 类。有关更多详细信息,请参阅 vignette("compatibility")。