如何在R中定义用于存储用户定义函数的类?

sk0*_*099 1 oop r

我来自使用C#,PHP,javascript等.对我来说,能够做类似的事情是有意义的:

class SomeClass {
    public function myFunction($var) {
        echo $var;
    }
}

$myClass = new SomeClass();

$myClass->myFunction('test');
Run Code Online (Sandbox Code Playgroud)

我想用R做这个 - 有没有相同的东西来帮助避免命名冲突?每次我加载一个包它告诉我在其他包中有通用名称的函数,我只是想避免这种情况.

Mar*_*gan 5

R参考类有'感觉'

.SomeClass <- setRefClass("SomeClass",
    methods = list(
      myFunction = function(var) {
          message(var)
      }))
Run Code Online (Sandbox Code Playgroud)

然后

> myClass <- .SomeClass()
> myClass$myFunction('test')
test
Run Code Online (Sandbox Code Playgroud)

在许多情况下,不同的解决方案是使用S3或S4对象系统,并在现有或新创建的泛型上实现方法.S4版可能看起来像

.A <- setClass("A",
  representation=representation(
    name="character",
    age="integer"))

A <- function(name=character(), age=integer(), ...)
    ## constructor: type check / coercion, then create
    .A(name=as.character(name), age=as.integer(age), ...)

setMethod("length", "A", function(x) {
    ## getGeneric("length") to discover existing generic
    length(x@name)
})

setMethod("show", "A", function(object) {
    ## how to display the object -- existing generic 'show'
    cat("class:", class(object), "\n")
    cat("length:", length(object), "\n")
    cat("name:", paste(sQuote(object@name), collapse=", "), "\n")
    cat("age:", paste(object@age, collapse=", "), "\n")
})

setGeneric("toupper")                   # no existing generic; create one

setMethod("toupper", "A", function(x) {
    ## use default 'initialize' method as copy constructor; return a
    ## new (updated) instance
    initialize(x, name=toupper(x@name))
})
Run Code Online (Sandbox Code Playgroud)

并在使用中:

> a <- A(c("fred", "ginger"), c(88, 83))
> a
class: A 
length: 2 
name: 'fred', 'ginger' 
age: 88, 83 
> toupper(a)
class: A 
length: 2 
name: 'FRED', 'GINGER' 
age: 88, 83 
Run Code Online (Sandbox Code Playgroud)

和S3版本(注意除了构造函数之外没有类定义):

B <- function(name, age) {
    obj <- list(name=as.character(name), age=as.integer(age))
    class(obj) <- "B"
    obj
}

length.B <- function(x)
    ## 'length' is an S3 generic, but hard to know
    length(x$name)

print.B <- function(x, ...) {
    ## 'print' at the command line contains body UseMethod --
    ## signalling an existing S3 generic
    cat("class:", class(x), "\n")
    cat("length:", length(x), "\n")
    cat("name:", paste(sQuote(x$name), collapse=", "), "\n")
    cat("age:", paste(x$age, collapse=", "), "\n")
}

toupper.default <- base::toupper

toupper <- function(x, ...)
    UseMethod("toupper")

toupper.B <- function(x, ...) {
    x$name <- toupper(x$name)
    x
}
Run Code Online (Sandbox Code Playgroud)

当现有函数中的新泛型的S3和S4实现时,可能会在从包中导出新泛型时导致关于"屏蔽"的消息,因此这对您的问题没有任何帮助.在上面的示例中,toupper()即使您的通用掩盖了原始定义,基本包中的可用功能也会保留; 当包A定义一个通用toupper时,S4中出现问题,而包B定义了一个通用toupper,因此用户需要消除歧义A::toupper()以获得正确的方法表.