1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
#### Testing UseMethod() and even more NextMethod()
#### --------------------
#### i.e., S3 methods *only*. For S4, see reg-S4.R
## ~~~~~~~~
###-- Group methods
## previous versions used print() and hit an auto-printing bug.
### Arithmetic "Ops" :
">.bar" <- function(...) {cat("using >.bar\n"); FALSE}
">.foo" <- function(...) {cat("using >.foo\n"); TRUE}
Ops.foo <- function(...) {
cat("using Ops.foo\n")
NextMethod()
}
Ops.bar <- function(...) {
cat("using Ops.bar\n")
TRUE
}
x <- 2:4 ; class(x) <- c("foo", "bar")
y <- 4:2 ; class(y) <- c("bar", "foo")
## The next 4 give a warning each about incompatible methods:
x > y
y < x # should be the same (warning msg not, however)
x == y
x <= y
x > 3 ##[1] ">.foo"
rm(list=">.foo")
x > 3 #-> "Ops.foo" and ">.bar"
### ------------ was ./mode-methods.R till R ver. 1.0.x ----------------
###-- Using Method Dispatch on "mode" etc :
## Tests S3 dispatch with the class attr forced to be data.class
## Not very relevant when S4 methods are around, but kept for historical interest
abc <- function(x, ...) {
cat("abc: Before dispatching; x has class `", class(x), "':", sep="")
str(x)
UseMethod("abc", x) ## UseMethod("abc") (as in S) fails
}
abc.default <- function(x, ...) sys.call()
"abc.(" <- function(x)
cat("'(' method of abc:", deparse(sys.call(sys.parent())),"\n")
abc.expression <- function(x)
cat("'expression' method of abc:", deparse(sys.call(sys.parent())),"\n")
abc(1)
e0 <- expression((x))
e1 <- expression(sin(x))
abc(e0)
abc(e1)
abc(e0[[1]])
abc(e1[[1]])
## Some tests for `nameOfClass()`, called from inherits()
ClassX <- structure(list(), name = "ClassX",
class = c("S3pp_class", "S3pp_object"))
classx_instance <- structure(list(), class = c("ClassX", "S3pp_object"))
nameOfClass.S3pp_class <- function(x) attr(x, "name", TRUE)
nameOfClass.foo <- function(x) "bar"
stopifnot(exprs = {
inherits(classx_instance, "ClassX")
inherits(classx_instance, ClassX)
## ignore class on a character object
isTRUE(inherits(1, structure("numeric", class = "foo")))
## make sure class is nor evaluated in calling nameOfClass
isFALSE(inherits(1, structure(quote(stop("should not be evaluated")),
class = "foo")))
})
## Some tests for `@` dispatching
## make sure that
## - `@` evals the first args only once,
## - doesn't dispatch for S4
## - works on `.Data` even for nonS4 objects
x <- structure(list(), class = "foo", prop1 = 'prop1val')
registerS3method("@", "foo",
function(x, name) {
stopifnot(typeof(name) == "character", length(name) == 1L)
cat(sprintf("called `@.foo`(x = %s, name = '%s')\n",
deparse1(substitute(x), "\n"), name))
attr(x, name, TRUE)
}
)
x@prop1
abc <- x
abc@prop1
{
cat("new x\n")
structure(list(), class = "foo", prop1 = 'prop1val')
}@prop1
makeActiveBinding("ax", function(x) {
cat("evaluating ax\n")
get("x", envir = parent.frame())
}, environment())
ax@prop1
stopifnot(exprs = {
identical( x@prop1, "prop1val")
identical(ax@prop1, "prop1val")
identical(letters@.Data, letters)
})
try(letters@foo) # error
# doesn't dispatch for S4
setClass("Person",
slots = c(
name = "character",
age = "numeric"
)
)
`@.Person` <- function(x, name) {
stop("called @.Person()\n")
}
p <- new("Person", name = "Who", age = -1)
stopifnot(p@name == "Who")
## Some tests for `chooseOpsMethod()`, called from C DispatchGroup() when
## 2 methods are found
foo_obj <- structure(1, class = "foo")
bar_obj <- structure(1, class = "bar")
`+.foo` <- function(e1, e2) "foo"
`+.bar` <- function(e1, e2) "bar"
invisible(foo_obj + bar_obj) # Warning: Incompatible methods
chooseOpsMethod.bar <- function(x, y, mx, my, cl, reverse) TRUE
stopifnot(exprs = {
identical(foo_obj + bar_obj, "bar")
identical(bar_obj + foo_obj, "bar")
})
|