2011-10-21 14 views
5

Mirando a S4 wiki de Hadley Wickham: https://github.com/hadley/devtools/wiki/S4constructores S4 y prototipos

setClass("Person", representation(name = "character", age = "numeric"), 
    prototype(name = NA_character_, age = NA_real_)) 
hadley <- new("Person", name = "Hadley") 

¿Cómo podemos diseñar un constructor para la persona (como este)

Person<-function(name=NA,age=NA){ 
new("Person",name=name,age=age) 
} 

que no hace esto:

> Person() 
Error in validObject(.Object) : 
    invalid class "Person" object: 1: invalid object for slot "name" in class "Person": got class "logical", should be or extend class "character" 
invalid class "Person" object: 2: invalid object for slot "age" in class "Person": got class "logical", should be or extend class "numeric" 
+0

Una actualización: setClass devuelve un constructor por defecto: persona <- setClass ("Persona", ...) – ctbrown

Respuesta

4

Parece que la respuesta está ahí en su ejemplo:

Person<-function(name=NA_character_,age=NA_real_){ 
new("Person",name=name,age=age) 
} 

produce

> Person() 
An object of class "Person" 
Slot "name": 
[1] NA 

Slot "age": 
[1] NA 

> Person("Moi") 
An object of class "Person" 
Slot "name": 
[1] "Moi" 

Slot "age": 
[1] NA 

> Person("Moi", 42) 
An object of class "Person" 
Slot "name": 
[1] "Moi" 

Slot "age": 
[1] 42 

Sin embargo, esto es bastante ONU-S4 y duplica los valores por defecto ya asignados en la definición de clase. Tal vez prefiera hacer

Person <- function(...) new("Person",...) 

y sacrificar la posibilidad de llamar sin argumentos con nombre?

3

Prefiero dar al usuario final algunas sugerencias sobre los tipos de argumentos que la sugerencia de usar ... por @themel. También se omite el prototipo y se usa length([email protected]) == 0 como indicación de que el campo no está inicializado, utilizando una clase People en lugar de Person, que refleja la estructura vectorizada de R y usa ... en el constructor para que las clases derivadas también puedan usar el constructor.

setClass("People", 
    representation=representation(
     firstNames="character", 
     ages="numeric"), 
    validity=function(object) { 
     if (length([email protected]) != length([email protected])) 
      "'firstNames' and 'ages' must have same length" 
     else TRUE 
    }) 

People = function(firstNames=character(), ages=numeric(), ...) 
    new("People", firstNames=firstNames, ages=ages, ...) 

Y

People(c("Me", "Myself", "I"), ages=c(NA_real_, 42, 12))