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
的函数更有用,它可以将 age
和 ageSquared
都设置为相关值。
另请注意,如果您将 setClass
的结果分配给一个对象(就像我在上面的示例中所做的那样,将其分配给一个名为 personInfo
的对象,那么 personInfo
变成 对 initialize
的调用,您现在可以调用例如
personInfo(age=10,ageSquared=100)
(尽管在这种情况下这并不理想,因为您必须显式提供 ageSquared
,而您本可以让该方法为您执行此操作。)
我会推荐:
- 为任何具有合理默认值的插槽使用原型(无论如何每个 class/slot 都有一个隐式原型)
- 始终将
setClass
中的 return 值作为对象保存
- 如果某些插槽依赖于其他插槽(例如此处的
ageSquared
),则使用 initialize
方法覆盖它
在 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
的函数更有用,它可以将 age
和 ageSquared
都设置为相关值。
另请注意,如果您将 setClass
的结果分配给一个对象(就像我在上面的示例中所做的那样,将其分配给一个名为 personInfo
的对象,那么 personInfo
变成 对 initialize
的调用,您现在可以调用例如
personInfo(age=10,ageSquared=100)
(尽管在这种情况下这并不理想,因为您必须显式提供 ageSquared
,而您本可以让该方法为您执行此操作。)
我会推荐:
- 为任何具有合理默认值的插槽使用原型(无论如何每个 class/slot 都有一个隐式原型)
- 始终将
setClass
中的 return 值作为对象保存 - 如果某些插槽依赖于其他插槽(例如此处的
ageSquared
),则使用initialize
方法覆盖它