我通过在对象上设置类来创建几个我控制的S3方法。像这样:
myfun <- function (x) {
UseMethod("myfun")
}
myfun.a <- function(x) {
print("Type a")
}
myfun.b <- function(x) {
print("Type b")
}
myfun.c <- function(x) {
print("Type c")
}
myfun(structure( c(1:3), class = "a"))
# [1] "Type a"
myfun(structure( c(1:3), class = "b"))
# [1] "Type b"
myfun(structure( c(1:3), class = "c"))
# [1] "Type c"
有时,类的某些子集能够共享类似这样的方法:
otherfun <- function (x) {
UseMethod("otherfun")
}
otherfun.a <- function(x) {
print("Type a")
}
otherfun.b <- function(x) { ## Doesn't work because its only called for "b"
print("Type b or c")
}
otherfun(structure( c(1:3), class = "a"))
# [1] "Type a"
otherfun(structure( c(1:3), class = "b"))
# [1] "Type b or c"
otherfun(structure( c(1:3), class = "c"))
# [1] "Type b or c"
实现共享方法的多个类类型的最佳/最正确方法是什么?我不想在对象上堆栈类,因为课程&#34; b&#34;和&#34; c&#34;在大多数方面都不同。
我正在考虑使用默认方法并手动解析类类型,例如:
otherfun <- function (x) {
UseMethod("otherfun")
}
otherfun.a <- function(x) {
print("Type a")
}
otherfun.b <- function(x) {
print("Type b or c")
}
otherfun.default <- function(x) {
if(class(x) == "c") otherfun.b(x)
else stop("Bad Class on x")
}
otherfun(structure( c(1:3), class = "a"))
# [1] "Type a"
otherfun(structure( c(1:3), class = "b"))
# [1] "Type b or c"
otherfun(structure( c(1:3), class = "c"))
# [1] "Type b or c"
答案 0 :(得分:4)
只需将它们分配到一起:
otherfun.b <- otherfun.c <- function(x) print("Type b or c")
答案 1 :(得分:4)
定义合适的班级层次
a <- structure(list(), class=c("a", "base"))
b <- structure(list(), class=c("b", "b_or_c", "base"))
c <- structure(list(), class=c("c", "b_or_c", "base"))
并在适当的地方实施方法
im <- function(x) UseMethod("im")
im.a <- function(x) "I'm a"
im.b_or_c <- function(x) paste("I'm b_or_c:", class(x)[1])
行动中:
> im(a)
[1] "I'm a"
> im(b)
[1] "I'm b_or_c: b"
> im(c)
[1] "I'm b_or_c: c"
通常,由于共享结构,类共享方法。定义适当的层次结构允许重用方法和数据结构。
同一个类的对象应始终具有相同的类层次结构,因此'b'将始终为'b_or_c'。这在许多对象系统中强制执行; S3允许您使用类定义进行非常快速和松散的播放。强制执行公共层次结构的一种方法是使用集中创建类
的“构造函数”base = function(base_data="base only", ..., class)
## construct an instance that contains base data, other data (...),
## and an appropriate class specification
structure(list(base_data=base_data, ...), class=c(class, "base"))
b_or_c = function(b_or_c_data="b or c", ..., class)
## construct a b_or_c instance with relevant data, using the
## base constructor
base(b_or_c_data=b_or_c_data, ..., class=c(class, "b_or_c"))
b = function(b_data="b only", ...)
## like b_or_c, but for a 'b' instance
b_or_c(b_data=b_data, ..., class="b")
在行动中看起来像
> b(b_data="ima b")
$base_data
[1] "base only"
$b_or_c_data
[1] "b or c"
$b_data
[1] "ima b"
attr(,"class")
[1] "b" "b_or_c" "base"
即使b_or_c上没有方法,让类表示在b和c类之间共享的数据仍然有用。如果没有,请删除b_or_c构造函数并调整b()
以致电base()
。
可能是a
与b
和c
共享方法,在这种情况下,该方法应该在基类上实现。当a
与b
但不是c
共享方法时,通常会编写a和b方法在初始处理后调用的辅助函数;通常这种模式(其中一个方法只在层次结构不同部分的某些类的对象上实现)表明类层次结构设计不合适
.foo_helper = function(x) {
## implement shared functionality here
}
foo.a = function(x) {
## do a-specfic things here, then
data = some_manipulation_of_a
.foo_helper(data)
}
foo.b = function(x) {
data = some_manipulation_of_b
.foo_helper(data)
}
可能这是一个比接受的答案更真实的模式 - a
和c
可能需要单独处理(因为它们有不同的数据结构),然后再调用一些共享功能。