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

时间:2015-01-18 19:55:10

标签: r oop

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

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

$myClass = new SomeClass();

$myClass->myFunction('test');

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

1 个答案:

答案 0 :(得分:5)

R参考班有这种感觉'

.SomeClass <- setRefClass("SomeClass",
    methods = list(
      myFunction = function(var) {
          message(var)
      }))

然后

> myClass <- .SomeClass()
> myClass$myFunction('test')
test

在许多情况下,不同的解决方案是使用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))
})

并在使用中:

> 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 

和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
}

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