R中具有自定义字段类的引用类? [英] Reference Class with custom field classes in R?

查看:98
本文介绍了R中具有自定义字段类的引用类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在另一个引用类中使用自定义引用类,但是此代码失败:

I would like to use a custom reference class inside another reference class, but this code fails:

nameClass <- setRefClass("nameClass", fields = list(first = "character",
                                                last = "character"),
                     methods = list(
                       initialize = function(char){
                         chunks <- strsplit(char,"\\.")
                         first <<- chunks[[1]][1]
                         last <<- chunks[[1]][2]
                       },
                       show = function(){
                         cat("Special Name Class \n:")
                         cat("First Name:")
                         methods::show(first)
                         cat("Last Name:")
                         methods::show(last)
                       }
                       ))
# this works fine
nameClass$new("tyler.durden")

当我尝试添加一个具有类nameClass的字段的第二个类时,该类无法启动.

When I try to add a second class that has a field of class nameClass this class cannot be initiated.

personClass <- setRefClass("personClass", fields = list(fullname = "nameClass",
                                                    occupation = "character"),
                       methods = list(
                         initialize = function(Obj){
                           nm  <- deparse(substitute(Obj))
                           fullname <<- nameClass$new(nm)
                           occupation <<- Obj
                         }))

这只会返回:

 Error in strsplit(char, "\\.") : 
 argument "char" is missing, with no default

我可以想象一个解决方案,其中nameClass是S4类,但是我读了一点后,就有点害怕将S4和引用类混合使用.我想缺少一些东西吗?还是我想更精确地定义此特定名称字段而不是仅使用字符"时,我是否应该简单地使用S4类?

I could imagine a solution where nameClass is an S4 class but I reading a little made me kind of afraid to mix S4 and reference classes. Am I missing somthing or should I simply use an S4 classes when I want to define this particular name field more exactly than just 'character'?

我还找到了此线程头衔大有希望,但不知道如何解决我的问题.

I also found this thread with a promising title but could not figure out how this could solve my problem.

推荐答案

这是S4系统中一个常见问题的一种变体,在继承中,必须使用零参数对new的调用才能起作用.这是由于实现继承的方式所致,在该方法中,实例化了基类,然后使用派生类中的值填充基类.要实例化基类,需要创建不带任何参数的基类.

This is a variation of a common issue in the S4 system, where for inheritance to work a call to new with zero arguments has to work. This is because of the way inheritance is implemented, where the base class is instantiated and then populated with values from the derived class. To instantiate the base class requires creating it without any arguments. That you have a problem is illustrated with

> nameClass()
Error in .Internal(strsplit(x, as.character(split), fixed, perl, useBytes)) : 
  'x' is missing

解决方案是在您的initialize方法中提供默认参数

and the solution is to provide a default argument in your initialize method

initialize=function(char=charcter()) { <...> }

或以其他方式安排(例如,通过测试initialize主体中的missing(char))对构造函数的无参数调用.

or to otherwise arranging (e.g., by testing missing(char) in the body of initialize) for a no-argument call to the constructor to work.

可能的编程最佳实践将指示initialize方法采用...参数并且其主体中具有callSuper(),以便派生类可以利用基类(例如,字段分配)功能.为了避免因未命名参数的无意匹配而引起的问题,我认为签名可能最终应该围绕着看起来像这样的模板构建

Probably programming best practice would dictate that the initialize method takes a ... argument and has callSuper() in its body, so that derived classes can take advantage of base class (e.g., field assignment) functionality. To avoid problems with inadvertent matching of unnamed arguments, I think the signature should probably end up built around a template that looks like

initialize(..., char=character()) { callSuper(...) }

此方案依赖于对空" nameClass的适当定义.以下内容可能有太多的见解和视角变化,因此无法立即使用,但是...容易想到将nameClass视为数据帧中的行",但是更好(因为R在矢量上的效果最佳)认为它是描述列.考虑到这一点,空" nameClass的合理表示形式是firstlast字段的长度均为0.然后

This scheme relies on a suitable definition of an 'empty' nameClass. The following probably has too much opinion and change of perspective to be immediately useful, but... It's tempting to think of nameClass as a 'row' in a data frame, but it's better (because R works best on vectors) to think of it as describing columns. With this in mind a reasonable representation of an 'empty' nameClass is where the first and last fields are each of length 0. Then

nameClass <- setRefClass("nameClass",
    fields = list(first = "character", last = "character"),
    methods = list(
      initialize = function(..., char=character()){
          if (length(char)) {
              names <- strsplit(char, ".", fixed=TRUE)
              .first <- vapply(names, "[[", character(1), 1)
              .last <- vapply(names, "[[", character(1), 2)
          } else {
              .first <- character()
              .last <- character()
          }
          callSuper(..., first=.first, last=.last)
      }, show = function(){
          .helper <- function(x)
              sprintf("%s%s", paste(sQuote(head(x)), collapse=", "),
                      if (length(x) > 6) ", ..." else "")
          cat("Special Name Class (n = ", length(first), ")\n", sep="")
          cat("First names:", .helper(first), "\n")
          cat("Last names:", .helper(last), "\n")
      }))

具有类似测试用例

> nameClass()
Special Name Class (n = 0)
First names:  
Last names:  
> nameClass(char="Paul.Simon")
Special Name Class (n = 1)
First names: 'Paul' 
Last names: 'Simon' 
> nameClass(char=c("Paul.Simon", "Frank.Sinatra"))
Special Name Class (n = 2)
First names: 'Paul', 'Frank' 
Last names: 'Simon', 'Sinatra' 
> nameClass(char=paste(LETTERS, letters, sep="."))
Special Name Class (n = 26)
First names: 'A', 'B', 'C', 'D', 'E', 'F', ... 
Last names: 'a', 'b', 'c', 'd', 'e', 'f', ... 

派生类可以定义为

personClass <- setRefClass("personClass",
    fields = list(fullname = "nameClass", occupation = "character"),
    methods = list(
      initialize = function(..., fullname=nameClass(),
                            occupation=character()) {
          callSuper(..., fullname=fullname, occupation=occupation)
      }))

具有类似测试用例

personClass()
personClass(fullname=nameClass())
personClass(fullname=nameClass(), occupation=character())
personClass(fullname=nameClass(char="some.one"), occupation="job")

这篇关于R中具有自定义字段类的引用类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆