6

Looking through Hadley Wickham's S4 wiki: https://github.com/hadley/devtools/wiki/S4

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

How can we design a constructor for Person (like this)

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

that doesn't do this:

> 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" 
1
  • An update: setClass returns a default constructor: Person <- SetClass( "Person", ... ) Commented Jun 13, 2014 at 14:18

2 Answers 2

4

It looks like the answer is right there in your example:

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

yields

> 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 

However, that is fairly un-S4 and duplicates the default values already assigned in the class definition. Maybe you'd prefer to do

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

and sacrifice the ability to call without named arguments?

Sign up to request clarification or add additional context in comments.

Comments

4

I'd prefer giving the end-user some hints about argument types than the suggestion to use ... by @themel. Also forgoing the prototype and using length(x@name) == 0 as an indication that the field is un-initialized, using a People class rather than Person, reflecting the vectorized structure of R, and using ... in the constructor so derived classes can also use the constructor.

setClass("People", representation=representation( firstNames="character", ages="numeric"), validity=function(object) { if (length(object@firstNames) != length(object@ages)) "'firstNames' and 'ages' must have same length" else TRUE }) People = function(firstNames=character(), ages=numeric(), ...) new("People", firstNames=firstNames, ages=ages, ...) 

And

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.