[Rd] Was: setValidity and "initialize" method conflict ? [in R-help]

John Chambers jmc at research.bell-labs.com
Thu Nov 20 15:53:54 MET 2003


Peter Ruckdeschel wrote:
> 
> Hello,
> 
> Thomas Stabla (statho3 at web.de) has already sent this
> question to R-help,  Wed, 12 Nov 2003 21:21:31 +0100,
> but we are not sure whether we should better post this
> mail to this audience than to R-help:
> 
> ---------------------------------------------------------------------
> 
> We are using S4-classes and want to force a validity check
> when an object is created.
> 
> How can this be done, when an "initalize" method has been
> set?

The basic point is that the call to validObject() occurs in the default
method for initialize(), and only when some arguments have been included
in the call to new() in addition to the class name.  (Do
getMethod("initialize") to see the definition.)

When you override the default method, you have a choice of whether to
call validObject() or not (you might not want to if you're fussy about
efficiency).

If you do want to validate the object, there are two ways to do so:

1- Use callNextMethod to call the default method as part of your method
(this is often a good idea anyway).

2- call validObject directly after initializing the object.

Here's an example, run against the current 1.8.1 patched.

R> validC1 <- function(object) {
    if (all(object at x > 0)) 
        TRUE
    else "Negative values not allowed in x slot"
}
R> setClass("C1", representation(x = "numeric"), validity = validC1)
[1] "C1"
R> setClass("C2", representation(id = "character"), contains = "C1")
[1] "C2"

By the way, in the validity method you should not return a call to
warning() as in your example.  The validity method just returns a
character string describing the problem.

To define an initialize method for C2 in the first way, do something
like:

R> setMethod("initialize", "C2", function(.Object, x, 
    id) {
    callNextMethod(.Object, x = x)
    .Object at id <- id
    .Object
})
[1] "initialize"

Then:
R> new("C2", x = 1, id = "OK")
An object of class "C2"
Slot "id":
[1] "OK"

Slot "x":
numeric(0)


R> try(new("C2", x = -1, id = "BAD!"))
Error in validObject(.Object) : Invalid "C2" object: Negative values not
allowed in x slot

The same effect is obtained in the second way by something like:

R> setMethod("initialize", "C2", function(.Object, x, 
    id) {
    .Object at x <- x
    .Object at id <- id
    validObject(.Object)
    .Object
})

John Chambers




> 
> -------------------------------------------------------------------------
> We got problems when using our own "initalize" method:
> 
> platform i686-pc-linux-gnu
> arch     i686
> os       linux-gnu
> system   i686, linux-gnu
> status
> major    1
> minor    7.1
> year     2003
> month    06
> day      16
> language R
> 
> [But the same behaviour ouccured under R 1.8.0]
> 
> Following piece of code works fine, just like we expected it to
> 
> -------------------------------------------------------------------------
>  >setClass("Foo", representation(woo = "numeric"))
> [1] "Foo"
>  >validFooObject <- function(object) {
> +   if(object at woo > 0) return(TRUE)
> +   else return("warning: negative value for woo")}
> 
>  >setValidity("Foo", validFooObject)
> [1] "Foo"
> 
>  >new("Foo", woo = 1) # all is fine
> An object of class "Foo"
> Slot "woo":
> [1] 1
> 
>  >new("Foo", woo = -1) # ok, negative value
> Error in validObject(.Object) : Invalid "Foo" object: warning: negative
> value for woo
> 
> -------------------------------------------------------------------------
> 
> Now, if i define a initialize method for Foo, things change (R had
> been restarted)
> 
> -------------------------------------------------------------------------
>  >setClass("Foo", representation(woo = "numeric"))
> [1] "Foo"
> 
>  >validFooObject <- function(object) {
> +   if(object at woo > 0) return(TRUE)
> +   else return("warning: negative value for woo")}
> 
>  >setValidity("Foo", validFooObject)
> [1] "Foo"
> 
>  >setMethod("initialize", "Foo", function(.Object, woo){
> +   .Object at woo = woo
> +   .Object})
> [1] "initialize"
> 
>  >new("Foo", woo = 1) # all is fine
> An object of class "Foo"
> Slot "woo":
> [1] 1
> 
>  >new("Foo", woo = -1) # ! no warning, object created!
> An object of class "Foo"
> Slot "woo":
> [1] -1
> -------------------------------------------------------------------------
> 
> Thank you for your attention.
> --
> 
> Peter Ruckdeschel
> 
> ______________________________________________
> R-devel at stat.math.ethz.ch mailing list
> https://www.stat.math.ethz.ch/mailman/listinfo/r-devel

-- 
John M. Chambers                  jmc at bell-labs.com
Bell Labs, Lucent Technologies    office: (908)582-2681
700 Mountain Avenue, Room 2C-282  fax:    (908)582-3340
Murray Hill, NJ  07974            web: http://www.cs.bell-labs.com/~jmc



More information about the R-devel mailing list