8

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

4

2 回答 2

6

参考类是 S4 类。所以也许你应该看到setClassand的帮助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 numeric and base .method is used
setRefClass( 
  Class="childNum", 
  fields=list( 
    .elt="numeric" 
  ), 
  contains=c("virtC")  
)


## child 2 
## field is char and .method is overwritten
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"
于 2014-01-15T16:50:49.157 回答
1

这是我正在考虑采用的一种方法,用于从继承的虚拟“接口”中捕获未实现的方法。它不会静态捕获不正确的实现,但如果您尝试实例化一个没有实现所有接口方法的对象,它会出错。与其在调用未实现的函数时等待运行时错误,不如在您尝试创建对象时立即炸弹。

辅助函数

用于在继承树中搜索接口的辅助函数。现在这个太基础了。我需要做的是爬树并检查自己继承接口类的父母......

.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, or 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
于 2018-09-12T21:28:03.050 回答