setClass 中初始化方法与原型之间在 R S4 中设置默认值的区别是什么?

What is distinction between initialize method vs prototype in setClass to set default values in R S4?

在 R S4 OOP 中,我知道有两种方法可以为特定的 class.

设置默认值

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)

任何人都可以详细说明这两者之间的区别,即为什么我们要包含一个单独的初始化方法而不是在 setClass() 中使用 prototype()? S4 最佳实践是什么?

提前感谢您的回复。

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

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

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

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

personInfo(age=10,ageSquared=100)

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

我会推荐:

  • 为任何具有合理默认值的插槽使用原型(无论如何每个 class/slot 都有一个隐式原型)
  • 始终将 setClass 中的 return 值作为对象保存
  • 如果某些插槽依赖于其他插槽(例如此处的 ageSquared),则使用 initialize 方法覆盖它