| 52846 |
jmc |
1 |
options(error = recover)
|
| 52960 |
jmc |
2 |
## simple call, only field names
|
|
|
3 |
fg <- setRefClass("foo", c("bar", "flag"))
|
|
|
4 |
f1<- new("foo")
|
|
|
5 |
f1$bar
|
|
|
6 |
f1 <- fg$new(flag = "testing")
|
|
|
7 |
f1$bar <- 1
|
|
|
8 |
stopifnot(identical(f1$bar, 1))
|
|
|
9 |
fg$methods(showAll = function() c(bar, flag))
|
|
|
10 |
stopifnot(all.equal(f1$showAll(), c(1, "testing")))
|
|
|
11 |
|
| 52903 |
jmc |
12 |
fg <- setRefClass("foo", list(bar = "numeric", flag = "character"),
|
| 52960 |
jmc |
13 |
methods = list(
|
| 52816 |
jmc |
14 |
addToBar = function(incr) {
|
| 52960 |
jmc |
15 |
b = bar + incr
|
|
|
16 |
bar <<- b
|
| 52816 |
jmc |
17 |
b
|
|
|
18 |
}
|
|
|
19 |
))
|
|
|
20 |
ff = new("foo", bar = 1.5)
|
|
|
21 |
stopifnot(identical(ff$bar, 1.5))
|
|
|
22 |
ff$bar <- pi
|
|
|
23 |
stopifnot(identical(ff$bar, pi))
|
| 52903 |
jmc |
24 |
## test against generator
|
| 52816 |
jmc |
25 |
|
| 52903 |
jmc |
26 |
f2 <- fg$new(bar = pi)
|
|
|
27 |
## identical does not return TRUE if *contents* of env are identical
|
|
|
28 |
stopifnot(identical(ff$bar, f2$bar), identical(ff$flag, f2$flag))
|
|
|
29 |
|
| 52960 |
jmc |
30 |
f2$flag <- "standard flag"
|
|
|
31 |
stopifnot(identical(f2$flag, "standard flag"))
|
| 52903 |
jmc |
32 |
|
| 52960 |
jmc |
33 |
## fg$lock("flag")
|
|
|
34 |
## tryCatch(f2$flag <- "other", error = function(e)e)
|
| 52816 |
jmc |
35 |
|
| 52960 |
jmc |
36 |
|
|
|
37 |
## add some accessor methods
|
|
|
38 |
fg$accessors("bar")
|
|
|
39 |
|
| 52816 |
jmc |
40 |
ff$setBar(1:3)
|
| 52960 |
jmc |
41 |
stopifnot(identical(ff$getBar(), 1:3))
|
| 52816 |
jmc |
42 |
|
|
|
43 |
ff$getBar()
|
|
|
44 |
stopifnot(all.equal(ff$addToBar(1), 2:4))
|
|
|
45 |
|
| 52960 |
jmc |
46 |
|
| 52903 |
jmc |
47 |
## Add a method
|
|
|
48 |
fg$methods(barTimes = function(x) {
|
|
|
49 |
"This method multiples field bar by argument x
|
|
|
50 |
and this string is self-documentation"
|
|
|
51 |
setBar(getBar() * x)})
|
|
|
52 |
|
|
|
53 |
ffbar <- ff$getBar()
|
|
|
54 |
ff$barTimes(10)
|
|
|
55 |
stopifnot(all.equal(ffbar * 10, ff$getBar()))
|
|
|
56 |
ff$barTimes(.1)
|
|
|
57 |
|
| 52846 |
jmc |
58 |
## inheritance. redefines flag so should fail:
|
| 52903 |
jmc |
59 |
stopifnot(is(tryCatch(setRefClass("foo2", list(b2 = "numeric", flag = "complex"),
|
| 52816 |
jmc |
60 |
contains = "foo",
|
| 52903 |
jmc |
61 |
refMethods = list(addBoth = function(incr) {
|
| 52816 |
jmc |
62 |
addToBar(incr) #uses inherited class method
|
|
|
63 |
setB2(getB2() + incr)
|
| 52903 |
jmc |
64 |
})),
|
|
|
65 |
error = function(e)e), "error"))
|
| 52846 |
jmc |
66 |
## but with flag as a subclass of "character", should work
|
| 52871 |
jmc |
67 |
setClass("ratedChar", contains = "character", representation(score = "numeric"))
|
| 52903 |
jmc |
68 |
foo2 <- setRefClass("foo2", list(b2 = "numeric", flag = "ratedChar"),
|
| 52846 |
jmc |
69 |
contains = "foo",
|
| 52960 |
jmc |
70 |
methods = list(addBoth = function(incr) {
|
| 52846 |
jmc |
71 |
addToBar(incr) #uses inherited class method
|
| 52960 |
jmc |
72 |
b2<<- b2 + incr
|
| 52816 |
jmc |
73 |
}))
|
| 52960 |
jmc |
74 |
## now lock the flag field; should still allow one write
|
|
|
75 |
foo2$lock("flag")
|
| 52903 |
jmc |
76 |
f2 <- foo2$new(bar = -3, flag = as("ANY", "ratedChar"), b2 = ff$bar)
|
| 52960 |
jmc |
77 |
## but not a second one
|
|
|
78 |
stopifnot(is(tryCatch(f2$flag <- "Try again",
|
|
|
79 |
error = function(e)e), "error"))
|
|
|
80 |
f22 <- foo2$new(bar = f2$bar)
|
|
|
81 |
## same story if assignment follows the initialization
|
|
|
82 |
f22$flag <- f2$flag
|
|
|
83 |
stopifnot(is(tryCatch(f22$flag <- "Try again",
|
|
|
84 |
error = function(e)e), "error"))
|
|
|
85 |
## Exporting superclass object
|
| 52903 |
jmc |
86 |
f22 <- fg$new(bar = f2$bar, flag = f2$flag)
|
|
|
87 |
f2e <- f2$export("foo")
|
|
|
88 |
stopifnot(identical(f2e$bar, f22$bar), identical(f2e$flag, f22$flag),
|
|
|
89 |
identical(class(f2e), class(f22)))
|
| 52871 |
jmc |
90 |
stopifnot(identical(f2$flag, as("ANY", "ratedChar")), identical(f2$bar, -3),
|
| 52816 |
jmc |
91 |
all.equal(f2$b2, 2:4+0))
|
|
|
92 |
f2$addBoth(-1)
|
|
|
93 |
stopifnot(all.equal(f2$bar, -4), all.equal(f2$b2, 1:3+0))
|
|
|
94 |
|
| 52960 |
jmc |
95 |
## test callSuper()
|
|
|
96 |
setRefClass("foo3", fields = list(flag2 = "ratedChar"),
|
|
|
97 |
contains = "foo2",
|
|
|
98 |
methods = list(addBoth = function(incr) {
|
| 52846 |
jmc |
99 |
callSuper(incr)
|
| 52960 |
jmc |
100 |
flag2 <<- as(paste(flag, paste(incr, collapse = ", "), sep = "; "), "ratedChar")
|
| 52816 |
jmc |
101 |
incr
|
|
|
102 |
}))
|
|
|
103 |
|
| 52960 |
jmc |
104 |
f2 <- foo2$new(bar = -3, flag = as("ANY", "ratedChar"), b2 = 1:3)
|
| 52846 |
jmc |
105 |
f3 <- new("foo3")
|
|
|
106 |
f3$import(f2)
|
|
|
107 |
stopifnot(all.equal(f3$b2, f2$b2), all.equal(f3$bar, f2$bar), all.equal(f3$flag, f2$flag))
|
| 52871 |
jmc |
108 |
f3$addBoth(1)
|
| 52960 |
jmc |
109 |
stopifnot(all.equal(f3$bar, -2), all.equal(f3$b2, 2:4+0),
|
|
|
110 |
all.equal(f3$flag2, as("ANY; 1", "ratedChar")))
|
| 52871 |
jmc |
111 |
|
| 52960 |
jmc |
112 |
## but the import should have used up the one write for $flag
|
|
|
113 |
stopifnot(is(tryCatch(f3$flag <- "Try again",
|
|
|
114 |
error = function(e)e), "error"))
|
|
|
115 |
|
|
|
116 |
## a class with an initialize method, and an extra slot
|
|
|
117 |
setOldClass(c("simple.list", "list"))
|
|
|
118 |
fg4 <- setRefClass("foo4",
|
|
|
119 |
contains = "foo2",
|
|
|
120 |
methods = list(
|
|
|
121 |
initialize = function(...) {
|
|
|
122 |
.self <- initFields(...)
|
|
|
123 |
.self@made = R.version
|
|
|
124 |
.self
|
|
|
125 |
}),
|
|
|
126 |
representation = list(made = "simple.list")
|
|
|
127 |
)
|
|
|
128 |
|
|
|
129 |
f4 <- new("foo4", flag = "another test", bar = 1:3)
|
|
|
130 |
stopifnot(identical(f4@made, R.version))
|
| 52985 |
jmc |
131 |
|
|
|
132 |
## simple active binding test
|
|
|
133 |
abGen <- setRefClass("ab",
|
|
|
134 |
fields = list(a = "ANY",
|
|
|
135 |
b = function(x) if(missing(x)) a else {a <<- x; x}))
|
|
|
136 |
|
|
|
137 |
ab1 <- abGen$new(a = 1)
|
|
|
138 |
|
|
|
139 |
stopifnot(identical(ab1$a, 1), identical(ab1$b, 1))
|
|
|
140 |
|
|
|
141 |
ab1$b <- 2
|
|
|
142 |
|
|
|
143 |
stopifnot(identical(ab1$a, 2), identical(ab1$b, 2))
|
| 53068 |
jmc |
144 |
|
|
|
145 |
## a simple editor for matrix objects. Method $edit() changes some
|
|
|
146 |
## range of values; method $undo() undoes the last edit.
|
|
|
147 |
mEditor <- setRefClass("matrixEditor",
|
|
|
148 |
fields = list( data = "matrix",
|
|
|
149 |
edits = "list"),
|
|
|
150 |
methods = list(
|
|
|
151 |
edit = function(i, j, value) {
|
|
|
152 |
## the following string documents the edit method
|
|
|
153 |
'Replaces the range [i, j] of the
|
|
|
154 |
object by value.
|
|
|
155 |
'
|
|
|
156 |
backup <-
|
|
|
157 |
list(i, j, data[i,j])
|
|
|
158 |
data[i,j] <<- value
|
|
|
159 |
edits <<- c(list(backup),
|
|
|
160 |
edits)
|
|
|
161 |
invisible(value)
|
|
|
162 |
},
|
|
|
163 |
undo = function() {
|
|
|
164 |
'Undoes the last edit() operation
|
|
|
165 |
and update the edits field accordingly.
|
|
|
166 |
'
|
|
|
167 |
prev <- edits
|
|
|
168 |
if(length(prev)) prev <- prev[[1]]
|
|
|
169 |
else stop("No more edits to undo")
|
|
|
170 |
edit(prev[[1]], prev[[2]], prev[[3]])
|
|
|
171 |
## trim the edits list
|
|
|
172 |
length(edits) <<- length(edits) - 2
|
|
|
173 |
invisible(prev)
|
|
|
174 |
}
|
|
|
175 |
))
|
|
|
176 |
xMat <- matrix(1:12,4,3)
|
|
|
177 |
xx <- mEditor$new(data = xMat)
|
|
|
178 |
xx$edit(2, 2, 0)
|
|
|
179 |
xx$data
|
|
|
180 |
xx$undo()
|
|
|
181 |
mEditor$help("undo")
|
|
|
182 |
stopifnot(all.equal(xx$data, xMat))
|
|
|
183 |
|
|
|
184 |
## add a method to save the object
|
|
|
185 |
mEditor$methods(
|
|
|
186 |
save = function(file) {
|
|
|
187 |
'Save the current object on the file
|
|
|
188 |
in R external object format.
|
|
|
189 |
'
|
|
|
190 |
base::save(.self, file = file)
|
|
|
191 |
}
|
|
|
192 |
)
|
|
|
193 |
|
|
|
194 |
tf <- tempfile()
|
|
|
195 |
xx$save(tf) #$
|
|
|
196 |
load(tf)
|
|
|
197 |
unlink(tf)
|
|
|
198 |
stopifnot(identical(xx$data, .self$data))
|
|
|
199 |
|
|
|
200 |
markViewer <- ""
|
|
|
201 |
setMarkViewer <- function(what)
|
|
|
202 |
markViewer <<- what
|
|
|
203 |
|
|
|
204 |
## Inheriting a reference class: a matrix viewer
|
|
|
205 |
mv <- setRefClass("matrixViewer",
|
|
|
206 |
fields = c("viewerDevice", "viewerFile"),
|
|
|
207 |
contains = "matrixEditor",
|
|
|
208 |
methods = list( view = function() {
|
|
|
209 |
dd <- dev.cur(); dev.set(viewerDevice)
|
|
|
210 |
devAskNewPage(FALSE)
|
|
|
211 |
matplot(data, main = paste("After",length(edits),"edits"))
|
|
|
212 |
dev.set(dd)},
|
|
|
213 |
edit = # invoke previous method, then replot
|
|
|
214 |
function(i, j, value) {
|
|
|
215 |
callSuper(i, j, value)
|
|
|
216 |
view()
|
|
|
217 |
}))
|
|
|
218 |
|
|
|
219 |
## initialize and finalize methods
|
|
|
220 |
mv$methods( initialize = function(...) {
|
|
|
221 |
viewerFile <<- tempfile("matrixView")
|
|
|
222 |
pdf(viewerFile)
|
|
|
223 |
viewerDevice <<- dev.cur()
|
|
|
224 |
message("Plotting to ", viewerFile)
|
|
|
225 |
dev.set(dev.prev())
|
|
|
226 |
setMarkViewer("ON")
|
|
|
227 |
initFields(...)
|
|
|
228 |
},
|
|
|
229 |
finalize = function() {
|
|
|
230 |
dev.off(viewerDevice)
|
|
|
231 |
setMarkViewer("OFF")
|
|
|
232 |
})
|
|
|
233 |
|
|
|
234 |
ff = new("matrixViewer", data = xMat)
|
|
|
235 |
stopifnot(identical(markViewer, "ON")) # check initialize
|
|
|
236 |
ff$edit(2,2,0)
|
|
|
237 |
ff$data
|
|
|
238 |
ff$undo()
|
|
|
239 |
stopifnot(all.equal(ff$data, xMat))
|
|
|
240 |
rm(ff)
|
|
|
241 |
gc()
|
|
|
242 |
stopifnot(identical(markViewer, "OFF")) #check finalize
|
| 53212 |
jmc |
243 |
|
|
|
244 |
## deal correctly with inherited methods and overriding existing
|
|
|
245 |
## methods from $methods(...)
|
|
|
246 |
refClassA <- setRefClass("refClassA", methods=list(foo=function() "A"))
|
|
|
247 |
refClassB <- setRefClass("refClassB", contains="refClassA")
|
|
|
248 |
mnames <- objects(getClass("refClassB")@refMethods)
|
|
|
249 |
refClassB$methods(foo=function() callSuper())
|
|
|
250 |
stopifnot(identical(refClassB$new()$foo(), "A"))
|
|
|
251 |
mnames2 <- objects(getClass("refClassB")@refMethods)
|
|
|
252 |
stopifnot(identical(mnames2[is.na(match(mnames2,mnames))], "foo#refClassA"))
|
|
|
253 |
refClassB$methods(foo=function() paste(callSuper(), "Version 2"))
|
|
|
254 |
stopifnot(identical(refClassB$new()$foo(), "A Version 2"))
|
|
|
255 |
stopifnot(identical(mnames2, objects(getClass("refClassB")@refMethods)))
|
| 53274 |
jmc |
256 |
|
|
|
257 |
if(methods:::.hasCodeTools()) {
|
|
|
258 |
## code warnings assigning locally to, or hiding, field names
|
|
|
259 |
stopifnot(is(tryCatch(mv$methods(test = function(x) {data <- x[!is.na(x)]; mean(data)}), warning = function(e)e), "warning"))
|
|
|
260 |
|
| 53335 |
jmc |
261 |
### formal arg test suppressed--see comment in .checkFieldsInMethod
|
|
|
262 |
## stopifnot(is(tryCatch(mv$methods(test2 = function(data) {data[!is.na(x)]}), warning = function(e)e), "warning"))
|
| 53274 |
jmc |
263 |
} else
|
|
|
264 |
warning("Can't run some tests: recommended package codetools is not available")
|
| 53330 |
jmc |
265 |
|
|
|
266 |
## tests (fragmentary by necessity) of promptClass for reference class
|
|
|
267 |
suppressMessages(promptClass("refClassB", filename = textConnection("ctxt", "w")))
|
|
|
268 |
## look for a method, inheritance, inherited method
|
|
|
269 |
stopifnot(length(c(grep("foo.*refClassA", ctxt),
|
|
|
270 |
grep("code{foo()}", ctxt, fixed = TRUE),
|
|
|
271 |
grep("linkS4class{refClassA", ctxt, fixed = TRUE))) >= 3)
|
|
|
272 |
rm(ctxt)
|
| 53382 |
jmc |
273 |
|
|
|
274 |
|
|
|
275 |
## tests related to subclassing environments. These really test code in the core, viz. builtin.c
|
|
|
276 |
a <- refClassA$new()
|
|
|
277 |
ev <- new.env(parent = a) # parent= arg
|
|
|
278 |
stopifnot(is.environment(ev))
|
|
|
279 |
foo <- function()"A"; environment(foo) <- a # environment of function
|
|
|
280 |
stopifnot(identical(as.environment(a), environment(foo)))
|
|
|
281 |
xx <- 1:10; environment(xx) <- a # environment attribute
|
|
|
282 |
stopifnot(identical(as.environment(a), environment(xx)))
|
|
|
283 |
|
|
|
284 |
|