请注意:我知道R是一种函数式语言,所以请不要咬我;-)
对于我的许多程序,采用面向对象编程方法给我带来了很好的体验。现在,我想知道在R中使用S4 Reference Classes时是否有办法区分公共方法和私有方法?
示例
类定义
对于我的许多程序,采用面向对象编程方法给我带来了很好的体验。现在,我想知道在R中使用S4 Reference Classes时是否有办法区分公共方法和私有方法?
示例
类定义
setRefClass("B",
field=list(
b.1="numeric",
b.2="logical"
),
methods=list(
thisIsPublic=function(...) {
thisIsPublic_ref(.self=.self, ...)
},
thisIsPrivate=function(...) {
thisIsPrivate_ref(.self=.self, ...)
}
)
)
setRefClass("A",
field=list(
a.1="B"
)
)
注意
通常我不会将实际的方法定义放在类定义中,而是将其分离为S4方法(即thisIsPublic_ref
),原因如下:
- 这样类定义保持清晰排列,在个别方法定义变得很大时更容易阅读。
- 它允许您随时切换到方法的功能性执行。假设
x
是某个类的实例,则可以调用foo_ref(.self=x)
而不是x$foo()
。 - 它允许您通过
compiler::cmpfun()
字节编译方法,我认为如果您只有“纯”引用类方法,则无法实现。
对于这个特定的示例来说,确实没有必要使它那么复杂,但我想仍然说明这种方法。
方法定义
setGeneric(
name="thisIsPublic_ref",
signature=c(".self"),
def=function(
.self,
...
) {
standardGeneric("thisIsPublic_ref")
}
)
setGeneric(
name="thisIsPrivate_ref",
signature=c(".self"),
def=function(
.self,
...
) {
standardGeneric("thisIsPrivate_ref")
}
)
require(compiler)
setMethod(
f="thisIsPublic_ref",
signature=signature(.self="B"),
definition=cmpfun(function(
.self,
...
){
.self$b.1 * 1000
})
)
setMethod(
f="thisIsPrivate_ref",
signature=signature(.self="B"),
definition=cmpfun(function(
.self,
...
){
.self$b.2
})
)
实例
x.b <- new("B", b.1=10, b.2=TRUE)
x.a <- new("A", a.1=x.b, a.2="hello world")
公有 vs. 私有
类 A
的实例(即 x.a
)应该允许使用类 B
的公有方法:
> x.a$a.1$thisIsPublic()
[1] 10000
类 A
的实例 (即 x.a
) 不应该允许使用类 B
的私有方法。因此,我希望这样的操作不起作用,即导致错误:
> x.a$a.1$thisIsPrivate()
[1] TRUE
有什么想法可以指定这个吗?
到目前为止,我想到的唯一方法:
在每个方法中添加一个sender
参数,显式地为每个方法调用指定它,并检查class(.self) == class(sender)
。但这似乎有点“显式”。
A
类的x.a
中作为B
类的实例的x.a$a.1
)只是我实现封装的一种方式。但你完全正确,这种方式无法真正区分公共和私有方法,因为最终调用方法的是a.1
而不是x.a
。我会考虑一个好的更新示例来使事情更清晰。 - Rappster