我在help(ReferenceClasses)
中的虚拟/抽象类中找不到多少 - 有人能提供创建一个基本示例吗?此外,如何指定虚方法并强制子类必须实现它?
答案 0 :(得分:5)
参考类是S4类。也许你应该看到setClass
和Classes
的帮助:
这是一个虚拟的例子:
# virtual Base Class
setRefClass(
Class="virtC",
fields=list(
.elt="ANY"
),
methods = list(
.method = function(){
print("Base virtual method is called")
}
),
contains=c("VIRTUAL")
)
## child 1
## field as char and .method is overwritten
setRefClass(
Class="childNum",
fields=list(
.elt="numeric"
),
contains=c("virtC")
)
## child 2
## field is numeric and base .method is used
setRefClass(
Class="childChar",
fields=list(
.elt="character"
),
methods = list(
.method = function(){print('child method is called')}
),
contains=c("virtC")
)
## new('virtA') ## thros an error can't isntantiate it
a = new("childChar",.elt="a")
b = new("childNum",.elt=1)
b$.method()
[1] "Base virtual method is called"
a$.method()
[1] "child method is called"
答案 1 :(得分:0)
我正在考虑采用这种方法从继承的虚拟“接口”中捕获未实现的方法。它不会静态捕获不正确的实现,但是如果您尝试实例化未实现所有接口方法的对象,则会出错。调用未实现的函数时,它不会等待运行时错误,而是会在您尝试创建对象时立即爆炸。
Helper函数可在继承树中搜索接口。现在这太基本了。我需要做的是爬树并检查自己继承了Interface类的父级...
.get_interface_methods <- function(.self) {
## Get the environment of the class being instantiated
env <- attributes(.self$.refClassDef)$refMethods
## get original interface methods
supers <- selectSuperClasses(class(.self))
methods <- unlist(lapply(supers, function(x) getRefClass(x)$methods()))
## check the body is NOT null in the concrete class environment
funs <- Filter(is.function, lapply(methods, get, envir=env))
null_fun_body <- vapply(Map(body, funs), is.null, T)
## return names of functions not implemented
vapply(funs[null_fun_body], attr, "", which="name")
}
实例化包含一个或多个接口的对象时调用的另一种帮助程序功能。
.validate_interface <- function(.self) {
methods <- get_interface_methods(.self)
## stop the world and print out the un-implemented methods
if (length(methods) > 0L) {
stop("Must implement interface methods: ", paste(methods, collapse = ", "))
}
}
Interface类在初始化期间仅调用validate函数。从Interface继承的类可以使用具有NULL
主体的任何函数来注册接口方法。我为此创建了一个简单的助手。
setRefClass(
"Interface",
methods = list(
initialize = function() {
validate(.self)
}), contains="VIRTUAL")
InterfaceMethod <- function() NULL
在这里,我使用具有NULL
主体的虚拟方法创建两个接口。
## Create an interface to be implemented
setRefClass(
"ITest1",
contains=c("VIRTUAL", "Interface"),
methods = list(
foo = InterfaceMethod,
bar = InterfaceMethod,
baz = InterfaceMethod
))
## create a second interface
setRefClass(
"ITest2",
contains=c("VIRTUAL", "Interface"),
methods = list(
spam = InterfaceMethod,
ham = InterfaceMethod
))
最后,我创建一个非虚拟的类定义,该类定义继承了我定义的两个接口。在定义中,我实现了两个接口函数foo
和baz
,但是没有实现bar
,spam
或ham
:
Obj <- setRefClass(
"Obj",
contains = c("ITest1", "ITest2"),
methods = list(
foo = function() "Implemented!",
baz = function() "Implemented!"
))
当我尝试实例化该对象时,出现错误。
> x <- Obj$new()
Error in validate(.self) :
Must implement interface methods: bar, ham, spam