如何创建(初始化)从其他S4 slots派生的slots原型?

3
假设我有一个S4类
setClass("Person", representation(name = "character", first_letter = "character")

我希望在对象初始化时自动填充插槽first_letter。类似于以下内容:

> jack <- new("Person", name = "Jack")
> print(jack)
# Slot "name":
# "Jack"
#
# Slot "first_letter":
# "J"

我认为我应该这样做:

setClass("Person", 
  representation(name = "character", first_letter = "character"),
  prototype(first_letter = substring(self@name, 1, 1))
)

当然,我可以编写一个单独的方法来实现此操作。但我特别关注的是调用“new”时将“first_letter”插槽初始化为来自另一个插槽的信息的情况。
非常感谢您的帮助!
2个回答

3

一种方法是将first_letter视为私有字段。

  1. 创建一个自定义构造函数(initiate),使用其他公共字段设置私有字段。
  2. 定义公共插槽的set/get,以保持更改其他字段时相同的逻辑。

这里是一个实现示例:

## Note the use of `.` for private field
## this is just a convention
Person <- setClass("Person", representation(Name = "character", 
                                            first_letter. = "character"))

## define setter and getter for public slots
setGeneric("Name", function(x) standardGeneric("Name"))
setMethod("Name","Person",function(x)  x@Name)
setGeneric("Name<-", function(x,value) standardGeneric("Name<-"))
setMethod("Name<-","Person",function(x,value){
  x@Name <- value
  x@first_letter. <- substring(value, 1, 1)
  x
})
## define the constructor
## Note that we don't give an argument to the ctor 
## to init the private field
setMethod ("initialize", signature  = "Person",
           definition = function (.Object,
                                  name) {
             .Object@Name <- name
             .Object@first_letter. <- substring(name, 1, 1)
             return (.Object)
           })

现在,通过创建一个对象来测试它:
> p <- Person(name="Amine")
> p
An object of class "Person"
Slot "Name":
[1] "Amine"
## the slot is automatically initialized
Slot "first_letter.":
[1] "A"

接下来是我们更改插槽值的部分:

> Name(p) <- "Xvalue"
> p
An object of class "Person"
Slot "Name":
[1] "Xvalue"
## Again the private slot is updated
Slot "first_letter.":
[1] "X"

哇,这太棒了!我真的很感激!:D - nev

1
prototype参数可以让您为对象槽提供默认值。但是,如果您打算在将数据分配给对象的槽之前对其进行某种预处理,则需要为您的类定义一个初始化方法。
此外,您可能希望使用slot参数... representation的工作方式相同,但它是针对S3继承而设计的,我不确定这是否是您想要的(请查看?setClass)。
然后定义您的类。
setClass ("Person", slots = c (name = "character", first_letter = "character"))

或者

setClass("Person", representation (name = "character", first_letter = "character"))

和初始化方法:

setMethod ("initialize", signature  = "Person",
           definition = function (.Object,
                                  name,
                                  first_letter = substring (name, 1, 1)) {
               .Object@name <- name
               .Object@first_letter <- first_letter
               return (.Object)
           })

注意:需要像这样调用.Object(与generic方法中定义的名称相同)。通常还需要记得return它...。
现在,您应该可以根据自己的需要进行初始化。
new("Person", name = "Jack")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接