我知道R中不同的OO系统的一般ins and outs,并且我会尽可能/尽可能地一直呆在S3中。
但是,对multiple dispatch的需求一直困扰着我在专业项目中的工作,过去一直使我进入S4。
但是我拒绝接受我找不到多重分发àS4的S3 仿真,它至少能够支持我避免非系统性data drift的主要用例:
如果我要通过某种版本控制方案描述数据结构(这是迄今为止我能想到的最好的方法),那么我基本上需要将我的方法基于关于方法分派的三个签名参数:
除了我读过的OO field guide:
针对input_class
和output_class
的基于S3的顺序方法,它们都可以在结构上随时间演变,这是由诸如v1
,{{1 }}等
v2
# Generic that dispatches on `x`
new_output_class <- function(x, schema_version_in, schema_version_out, ...) {
UseMethod("new_output_class", x)
}
# Generic that dispatches on 'schema_version_in' and
# can thus be used to define distinct methods for
# different versions of 'input_class'
new_output_class__input_class <- function(x, schema_version_in,
schema_version_out, ...) {
UseMethod("new_output_class__input_class", schema_version_in)
}
# Generic that dispatches on 'schema_version_out' and
# can thus be used to define distinct methods for
# different versions of 'output_class' for inputs of class `input_class`
# with version class `v1`
new_output_class__input_class__v1 <- function(x, schema_version_in,
schema_version_out, ...) {
UseMethod("new_output_class__input_class__v1", schema_version_out)
}
# Top-level method for dispatch based on `input_class`
new_output_class.input_class <- function(
x,
schema_version_in,
schema_version_out
) {
message("Level 1: method for `input_class`")
new_output_class__input_class(x, schema_version_in, schema_version_out)
}
和input_class = v1
的初始情况定义方法output_class = v1
library(magrittr)
library(stringr)
# Method for `input_class` of version `v1`
new_output_class__input_class.v1 <- function(
x,
schema_version_in,
schema_version_out
) {
# message("Sub-level 1: `input_class/in:v1`")
message(stringr::str_glue("Level 2: method for `input_class/in:{schema_version_in}`"))
new_output_class__input_class__v1(x, schema_version_in, schema_version_out)
}
# Method for `output_class` of version `v1` for inputs
# of `input_class` of version `v1`
new_output_class__input_class__v1.v1 <- function(
x,
schema_version_in,
schema_version_out
) {
message(stringr::str_glue("Level 3: method for `input_class/in:{schema_version_in}/out:{schema_version_out}`"))
structure(x,
class = c(stringr::str_glue("output_class_{schema_version_out}"),
"output_class")
)
}
x <- structure(letters[1:3], class = "input_class")
schema_version_of_x <- structure("v1", class = "v1")
schema_version_of_new_output <- structure("v1", class = "v1")
new_output_class(x, schema_version_of_x, schema_version_of_new_output)
# Level 1: method for `input_class`
# Level 2: method for `input_class/in:v1`
# Level 3: method for `input_class/in:v1/out:v1`
# [1] "a" "b" "c"
# attr(,"class")
# [1] "output_class_v1" "output_class"
到output_class
的演变v2
# Method for `output_class` of version `v2` for inputs
# of `input_class` of version `v1`
new_output_class__input_class__v1.v2 <- function(
x,
schema_version_in,
schema_version_out
) {
message(stringr::str_glue("Level 3: method for `input_class/in:{schema_version_in}/out:{schema_version_out}`"))
structure(x %>% rep(2),
class = c(stringr::str_glue("output_class_{schema_version_out}"),
"output_class")
)
}
schema_version_of_new_output <- structure("v2", class = "v2")
new_output_class(x, schema_version_of_x, schema_version_of_new_output)
# Level 1: method for `input_class`
# Level 2: method for `input_class/in:v1`
# Level 3: method for `input_class/in:v1/out:v2`
# [1] "a" "b" "c" "a" "b" "c"
# attr(,"class")
# [1] "output_class_v2" "output_class"
到input_class
的演变v2
有人在S3中提出了更好的多调度模拟吗?