如何在R中创建虚拟引用类?

时间:2014-01-15 16:24:41

标签: r class oop reference-class

我在help(ReferenceClasses)中的虚拟/抽象类中找不到多少 - 有人能提供创建一个基本示例吗?此外,如何指定虚方法并强制子类必须实现它?

2 个答案:

答案 0 :(得分:5)

参考类是S4类。也许你应该看到setClassClasses的帮助:

这是一个虚拟的例子:

# 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
  ))

实例化对象

最后,我创建一个非虚拟的类定义,该类定义继承了我定义的两个接口。在定义中,我实现了两个接口函数foobaz,但是没有实现barspamham

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