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