R : Copyright 2006, The R Foundation for Statistical Computing Version 2.3.0 Under development (unstable) (2006-02-09 r37310) ISBN 3-900051-07-0 R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help. Type 'q()' to quit R. > ##--- S4 Methods (and Classes) > library(methods) > ##too fragile: showMethods(where = "package:methods") > > ##-- S4 classes with S3 slots [moved from ./reg-tests-1.R] > setClass("test1", representation(date="POSIXct")) [1] "test1" > x <- new("test1", date=as.POSIXct("2003-10-09")) > stopifnot(format(x @ date) == "2003-10-09") > ## line 2 failed in 1.8.0 because of an extraneous space in "%in%" > > stopifnot(all.equal(3:3, 3.), all.equal(1., 1:1)) > > ## trace (requiring methods): > f <- function(x, y) { c(x,y)} > xy <- 0 > trace(f, quote(x <- c(1, x)), exit = quote(xy <<- x), print = FALSE) [1] "f" > fxy <- f(2,3) > stopifnot(identical(fxy, c(1,2,3))) > stopifnot(identical(xy, c(1,2))) > untrace(f) > > ## a generic and its methods > > setGeneric("f") [1] "f" > setMethod("f", c("character", "character"), function(x, y) paste(x,y)) [1] "f" > > ## trace the generic > trace("f", quote(x <- c("A", x)), exit = quote(xy <<- c(x, "Z")), print = FALSE) [1] "f" > > ## should work for any method > > stopifnot(identical(f(4,5), c("A",4,5)), + identical(xy, c("A", 4, "Z"))) > > stopifnot(identical(f("B", "C"), paste(c("A","B"), "C")), + identical(xy, c("A", "B", "Z"))) > > ## trace a method > trace("f", sig = c("character", "character"), quote(x <- c(x, "D")), + exit = quote(xy <<- xyy <<- c(x, "W")), print = FALSE) [1] "f" > > stopifnot(identical(f("B", "C"), paste(c("A","B","D"), "C"))) > # These two got broken by Luke's lexical scoping fix > #stopifnot(identical(xy, c("A", "B", "D", "W"))) > #stopifnot(identical(xy, xyy)) > > ## but the default method is unchanged > stopifnot(identical(f(4,5), c("A",4,5)), + identical(xy, c("A", 4, "Z"))) > > removeGeneric("f") [1] TRUE > ## end of moved from trace.Rd > > > ## print/show dispatch [moved from ./reg-tests-2.R ] > setClass("bar", representation(a="numeric")) [1] "bar" > foo <- new("bar", a=pi) > foo An object of class "bar" Slot "a": [1] 3.141593 > show(foo) An object of class "bar" Slot "a": [1] 3.141593 > print(foo) An object of class "bar" Slot "a": [1] 3.141593 > > setMethod("show", "bar", function(object){cat("show method\n")}) [1] "show" > show(foo) show method > foo show method > print(foo) show method > print(foo, digits = 4) An object of class "bar" Slot "a": [1] 3.142 > > print.bar <- function(x, ...) cat("print method\n") > foo print method > print(foo) print method > show(foo) show method > > setMethod("print", "bar", function(x, ...){cat("S4 print method\n")}) Creating a new generic function for 'print' in '.GlobalEnv' [1] "print" > foo S4 print method > print(foo) S4 print method > show(foo) show method > print(foo, digits = 4) S4 print method > > setClassUnion("integer or NULL", members = c("integer","NULL")) [1] "integer or NULL" > setClass("c1", representation(x = "integer", code = "integer or NULL")) [1] "c1" > nc <- new("c1", x = 1:2) > str(nc)# gave ^ANULL^A in 2.0.0 Formal class 'c1' [package ".GlobalEnv"] with 2 slots ..@ x : int [1:2] 1 2 ..@ code: NULL > ## > > > library(stats4) > ## the following showMethods() output tends to generate errors in the tests > ## whenever the contents of the packages change. Searching in the > ## diff's can easily mask real problems. If there is a point > ## to the printout, e.g., to verify that certain methods exist, > ## hasMethod() would be a useful replacement > > ## showMethods(where = "package:stats4") > ## showMethods("show") > ## showMethods("show") > ## showMethods("plot") # (ANY,ANY) and (profile.mle, missing) > ## showMethods(classes="mle") > ## showMethods(classes="matrix") > ## showMethods(classes=c("matrix", "numeric")) > ## showMethods(where = "package:methods") > > ## stopifnot(require(Matrix), > ## require(lme4)) # -> S4 plot > ## showMethods("plot") # more than last time > ## showMethods("show", classes = c("dgeMatrix","Matrix","matrix")) > ## showMethods("show") > ## showMethods(classes = c("dgeMatrix","matrix")) > > ##--- "[" fiasco before R 2.2.0 : > d2 <- data.frame(b= I(matrix(1:6,3,2))) > ## all is well: > d2[2,] [,1] [,2] [1,] 2 5 > stopifnot(identical(d2[-1,], d2[2:3,])) > ## Now make "[" into S4 generic by defining a trivial method > setClass("Mat", representation(Dim = "integer", "VIRTUAL")) [1] "Mat" > setMethod("[", signature(x = "Mat", + i = "missing", j = "missing", drop = "ANY"), + function (x, i, j, drop) x) [1] "[" > ## Can even remove the method: it doesn't help > removeMethod("[", signature(x = "Mat", + i = "missing", j = "missing", drop = "ANY")) [1] TRUE > d2[1:2,] ## used to fail badly; now okay [,1] [,2] [1,] 1 4 [2,] 2 5 > stopifnot(identical(d2[-1,], d2[2:3,])) > ## failed in R <= 2.1.x > > > ## Fritz' S4 "odditiy" > setClass("X", representation(bar="numeric")) [1] "X" > setClass("Y", contains="X") [1] "Y" > ## Now we define a generic foo() and two different methods for "X" and > ## "Y" objects for arg missing: > setGeneric("foo", function(object, arg) standardGeneric("foo")) [1] "foo" > setMethod("foo", signature(object= "X", arg="missing"), + function(object, arg) cat("an X object with bar =", object@bar, "\n")) [1] "foo" > setMethod("foo", signature(object= "Y", arg="missing"), + function(object, arg) cat("a Y object with bar =", object@bar, "\n")) [1] "foo" > ## Finally we create a method where arg is "logical" only for class > ## "X", hence class "Y" should inherit that: > setMethod("foo", signature(object= "X", arg= "logical"), + function(object, arg) cat("Hello World!\n") ) [1] "foo" > ## now create objects and call methods: > y <- new("Y", bar=2) > showMethods("foo") Function "foo": object = "X", arg = "missing" object = "X", arg = "logical" object = "Y", arg = "missing" > foo(y) a Y object with bar = 2 > foo(y, arg=TRUE)## Hello World! Hello World! > ## OK, inheritance worked, and we have > showMethods("foo") Function "foo": object = "X", arg = "missing" object = "X", arg = "logical" object = "Y", arg = "missing" object = "Y", arg = "logical" (inherited from object = "X", arg = "logical") > foo(y) a Y object with bar = 2 > ## still 'Y' -- was 'X object' in R < 2.3 > > > ## Multiple inheritance > setClass("A", representation(x = "numeric")) [1] "A" > setClass("B", representation(y = "character")) [1] "B" > setClass("C", contains = c("A", "B"), representation(z = "logical")) [1] "C" > new("C") An object of class "C" Slot "z": logical(0) Slot "x": numeric(0) Slot "y": character(0) > setClass("C", contains = c("A", "B"), representation(z = "logical"), + prototype = prototype(x = 1.5, y = "test", z = TRUE)) [1] "C" > (cc <- new("C")) An object of class "C" Slot "z": [1] TRUE Slot "x": [1] 1.5 Slot "y": [1] "test" > ## failed reconcilePropertiesAndPrototype(..) after svn r37018 >