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

时间:2016-07-08 20:47:34

标签: r class initialization 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时使用来自另一个插槽的信息启动的情况。

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分: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需要像这样调用(在泛型方法中定义的同名)。 通常你也要记得return它......

现在您应该可以根据需要进行初始化

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