r语言 - 如何对从其他插槽派生的 S4 插槽进行原型设计(启动)



假设我有一个 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))
)

当然,我可以在单独的语句中编写一种方法来执行此操作。我对调用first_letter时使用来自另一个插槽的信息启动new的情况特别感兴趣。

任何帮助将不胜感激!

一种方法是将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"

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需要像这样调用(与泛型方法中定义的名称相同)。通常你还必须记得return它...

现在你应该能够根据需要初始化

new("Person", name = "Jack")

最新更新