首页 > 解决方案 > 在 R S4 中设置默认值的 setClass 中的初始化方法与原型有什么区别?

问题描述

在 R S4 OOP 中,我知道有两种方法可以为特定类设置默认值。

1.) 在中使用原型setClass()

setClass("Person",
         slots = c(
           name = "character",
           age = "numeric"
         ), 
         prototype = list(
           name = "Jim",
           age = 25
         )
         )

2.) 使用初始化setMethod()

setMethod("initialize", "Person",
          function(.Object,
                   name,
                   age,
                   ...) {
              .Object@name <- "Jim"
              .Object@age <- 25
            validObject(.Object)
            return(.Object)
          }
)

assign("Person", Person, envir = .GlobalEnv)

谁能详细说明这两者之间的区别,即为什么我们要包含一个单独的初始化方法与使用prototype()in setClass()?什么是 S4 最佳实践?

预先感谢您的回复。

标签: rs4

解决方案


原型只能处理简单的情况;特别是插槽的值不能相互依赖,用户不能指定任何动态值。例如,如果您有一个简单的类

setClass("personInfo",
  slots=list(
    age="numeric",
    ageSquared="numeric"
  ), prototype=prototype(
    age=18,
    ageSquared=18^2
) -> personInfo

那么原型只能创造18岁的人。相反,创建一个作为 的函数的初始化方法更有用,age然后它可以同时设置ageageSquared相关的值。

另请注意,如果您将结果分配给setClass一个对象(就像我在上面的示例中所做的那样,将其分配给一个名为personInfothen的对象将personInfo 成为一个调用initialize,您现在可以调用例如

personInfo(age=10,ageSquared=100)

(尽管在这种情况下这并不理想,因为您必须明确提供ageSquared何时可以让该方法为您执行此操作。)

我会推荐:

  • 对任何具有合理默认值的槽使用原型(无论如何,每个类/槽都有一个隐式原型)
  • 始终将返回值保留setClass为对象
  • initialize使用某些插槽是否依赖于其他插槽的方法来覆盖它(例如ageSquared此处)

推荐阅读