如何原型(启动)从其他插槽派生的 S4 插槽?

How to prototype (initiate) S4 slots derived from other slots?

假设我有一个 S4 class

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))
)

当然,我可以在单独的语句中编写一个方法来执行此操作。我对 first_letter 插槽在调用 new.

时使用来自另一个插槽的信息启动的情况特别感兴趣

非常感谢任何帮助!

prototype 参数可让您为对象槽指定默认值。 但是由于您打算在将数据分配给对象中的插槽之前对数据进行某种预处理, 你需要定义一个 你的 class.

的初始化 方法

您可能还想使用 slot 参数... representation 效果一样, 但它是为 S3 继承而设计的,我不确定这是你想要的(检查 ?setClass

然后定义你的class

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")

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

  1. 创建使用其他 public 字段设置私有字段的自定义构造函数 (initiate)
  2. 为 public 个槽定义 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"