The R Project SVN R

Rev

Rev 62700 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
52960 jmc 1
## simple call, only field names
2
fg <- setRefClass("foo", c("bar", "flag"))
61035 jmc 3
f0 <- new("foo")  # deprecated, but should still work
4
f1 <- fg(flag = "testing")
52960 jmc 5
f1$bar <- 1
6
stopifnot(identical(f1$bar, 1))
61035 jmc 7
## add method
52960 jmc 8
fg$methods(showAll = function() c(bar, flag))
9
stopifnot(all.equal(f1$showAll(), c(1, "testing")))
56985 maechler 10
str(f1)
52960 jmc 11
 
56211 maechler 12
fg <- setRefClass("foo", list(bar = "numeric", flag = "character",
13
                              tag = "ANY"),
14
                  methods = list(addToBar = function(incr) {
15
                      b <- bar + incr
16
                      bar <<- b
17
                      b
18
                  } )
19
                  )
57589 jmc 20
fg$lock("flag")
21
stopifnot(identical(fg$lock(), "flag"))
22
 
56211 maechler 23
ff <- new("foo", bar = 1.5)
52816 jmc 24
stopifnot(identical(ff$bar, 1.5))
25
ff$bar <- pi
26
stopifnot(identical(ff$bar, pi))
57589 jmc 27
## flag has not yet been set
28
ff$flag <- "flag test"
29
stopifnot(identical(ff$flag, "flag test"))
30
## but no second assign
31
stopifnot(is(tryCatch(ff$flag <- "new", error = function(e)e), "error"))
32
 
52903 jmc 33
## test against generator
52816 jmc 34
 
61035 jmc 35
f2 <- fg(bar = pi, flag = "flag test")
52903 jmc 36
## identical does not return TRUE if *contents* of env are identical
37
stopifnot(identical(ff$bar, f2$bar), identical(ff$flag, f2$flag))
57589 jmc 38
## but flag was now assigned once
39
stopifnot(is(tryCatch(f2$flag <- "new", error = function(e)e), "error"))
52903 jmc 40
 
56985 maechler 41
str(f2)
42
 
52816 jmc 43
 
52960 jmc 44
## add some accessor methods
45
fg$accessors("bar")
46
 
52816 jmc 47
ff$setBar(1:3)
52960 jmc 48
stopifnot(identical(ff$getBar(), 1:3))
52816 jmc 49
 
50
ff$getBar()
51
stopifnot(all.equal(ff$addToBar(1), 2:4))
52
 
52960 jmc 53
 
52903 jmc 54
## Add a method
55
fg$methods(barTimes = function(x) {
56
    "This method multiples field bar by argument x
57
and this string is self-documentation"
58
    setBar(getBar() * x)})
59
 
60
ffbar <- ff$getBar()
61
ff$barTimes(10)
62
stopifnot(all.equal(ffbar * 10, ff$getBar()))
63
ff$barTimes(.1)
64
 
52846 jmc 65
## inheritance.  redefines flag so should fail:
56211 maechler 66
stopifnot(is(tryCatch(setRefClass("foo2", list(b2 = "numeric",
67
					       flag = "complex"),
52816 jmc 68
            contains = "foo",
52903 jmc 69
            refMethods = list(addBoth = function(incr) {
52816 jmc 70
                addToBar(incr) #uses inherited class method
71
                setB2(getB2() + incr)
52903 jmc 72
                })),
73
          error = function(e)e), "error"))
57604 jmc 74
## but with flag as a subclass of "characters", should work
56045 jmc 75
## Also subclasses "tag" which had class "ANY before
56211 maechler 76
setClass("ratedChar", contains = "character",
77
         representation(score = "numeric"))
78
foo2 <- setRefClass("foo2", list(b2 = "numeric", flag = "ratedChar",
79
				 tag = "numeric"),
80
	    contains = "foo",
81
	    methods = list(addBoth = function(incr) {
52846 jmc 82
                addToBar(incr) #uses inherited class method
56211 maechler 83
                b2 <<- b2 + incr
52816 jmc 84
                }))
52960 jmc 85
## now lock the flag field; should still allow one write
86
foo2$lock("flag")
61035 jmc 87
f2 <- foo2(bar = -3, flag = as("ANY", "ratedChar"),
56211 maechler 88
               b2 = ff$bar, tag = 1.5)
52960 jmc 89
## but not a second one
90
stopifnot(is(tryCatch(f2$flag <- "Try again",
91
         error = function(e)e), "error"))
56985 maechler 92
str(f2)
61035 jmc 93
f22 <- foo2(bar = f2$bar)
52960 jmc 94
## same story if assignment follows the initialization
95
f22$flag <- f2$flag
96
stopifnot(is(tryCatch(f22$flag <- "Try again",
97
         error = function(e)e), "error"))
98
## Exporting superclass object
61035 jmc 99
f22 <- fg(bar = f2$bar, flag = f2$flag)
52903 jmc 100
f2e <- f2$export("foo")
101
stopifnot(identical(f2e$bar, f22$bar), identical(f2e$flag, f22$flag),
102
          identical(class(f2e), class(f22)))
56211 maechler 103
stopifnot(identical(f2$flag,  as("ANY", "ratedChar")),
104
          identical(f2$bar, -3),
52816 jmc 105
          all.equal(f2$b2, 2:4+0))
106
f2$addBoth(-1)
107
stopifnot(all.equal(f2$bar, -4), all.equal(f2$b2, 1:3+0))
108
 
52960 jmc 109
## test callSuper()
57183 jmc 110
foo3 <- setRefClass("foo3", fields = list(flag2 = "ratedChar"),
52960 jmc 111
            contains = "foo2",
56211 maechler 112
	    methods = list(addBoth = function(incr) {
113
		callSuper(incr)
114
		flag2 <<- as(paste(flag, paste(incr, collapse = ", "),
115
				   sep = "; "),
116
                             "ratedChar")
52816 jmc 117
                incr
118
            }))
119
 
61035 jmc 120
f2 <- foo2(bar = -3, flag = as("ANY", "ratedChar"), b2 =  1:3)
121
f3 <- foo3()
52846 jmc 122
f3$import(f2)
56211 maechler 123
stopifnot(all.equal(f3$b2, f2$b2), all.equal(f3$bar, f2$bar),
124
          all.equal(f3$flag, f2$flag))
52871 jmc 125
f3$addBoth(1)
52960 jmc 126
stopifnot(all.equal(f3$bar, -2), all.equal(f3$b2, 2:4+0),
127
          all.equal(f3$flag2, as("ANY; 1", "ratedChar")))
52871 jmc 128
 
52960 jmc 129
## but the import should have used up the one write for $flag
130
stopifnot(is(tryCatch(f3$flag <- "Try again",
131
         error = function(e)e), "error"))
56985 maechler 132
str(f3)
52960 jmc 133
 
57604 jmc 134
## importing the same class (not very useful but documented to work)
61035 jmc 135
f3 <- foo3()
136
f4 <- foo3(bar = -3, flag = as("More", "ratedChar"), b2 =  1:3, flag2 = f2$flag)
57604 jmc 137
f3$import(f4)
138
stopifnot(identical(f3$bar, f4$bar),
139
          identical(f3$flag, f4$flag),
140
          identical(f3$b2, f4$b2),
141
          identical(f3$flag2, f4$flag2))
142
 
61035 jmc 143
## similar to $import() but using superclass object in the generator call
57183 jmc 144
## The explicitly supplied flag= should override and be allowed
57589 jmc 145
## by the default $initialize()
61035 jmc 146
f3b <- foo3(f2, flag = as("Other", "ratedChar"),
57183 jmc 147
                flag2 = as("More", "ratedChar"))
148
## check that inherited and direct field assignments worked
149
stopifnot(identical(f3b$tag, f2$tag),
150
          identical(f3b$flag, as("Other", "ratedChar")),
151
          identical(f3b$flag2, as("More", "ratedChar")))
61035 jmc 152
## the $new() method should match the generator function
153
f3b <- foo3$new(f2, flag = as("Other", "ratedChar"),
154
                flag2 = as("More", "ratedChar"))
155
stopifnot(identical(f3b$tag, f2$tag),
156
          identical(f3b$flag, as("Other", "ratedChar")),
157
          identical(f3b$flag2, as("More", "ratedChar")))
57589 jmc 158
## a class with an initialize method, and an extra slot (legal, not a good idea)
52960 jmc 159
setOldClass(c("simple.list", "list"))
160
fg4 <- setRefClass("foo4",
161
            contains = "foo2",
162
            methods = list(
163
              initialize = function(...) {
55779 jmc 164
                  .self$initFields(...)
165
                  .self@made <<- R.version
52960 jmc 166
                  .self
167
              }),
168
            representation = list(made = "simple.list")
169
            )
170
 
57589 jmc 171
f4 <- new("foo4", flag = as("another test", "ratedChar"), bar = 1:3)
52960 jmc 172
stopifnot(identical(f4@made, R.version))
52985 jmc 173
 
56036 jmc 174
## a trivial class with no fields, using fields = list(), failed up to rev 56035
175
foo5 <- setRefClass("foo5", fields = list(),
56211 maechler 176
                    methods = list(bar = function(test)
177
                    paste("*",test,"*")))
56036 jmc 178
 
61035 jmc 179
f5 <- foo5()
56036 jmc 180
stopifnot(identical( f5$bar("xxx"), paste("*","xxx", "*")))
181
 
182
 
52985 jmc 183
## simple active binding test
184
abGen <- setRefClass("ab",
185
                  fields = list(a = "ANY",
186
                  b = function(x) if(missing(x)) a else {a <<- x; x}))
187
 
61035 jmc 188
ab1 <- abGen(a = 1)
52985 jmc 189
 
190
stopifnot(identical(ab1$a, 1), identical(ab1$b, 1))
191
 
192
ab1$b <- 2
193
 
194
stopifnot(identical(ab1$a, 2), identical(ab1$b, 2))
53068 jmc 195
 
196
## a simple editor for matrix objects.  Method  $edit() changes some
197
## range of values; method $undo() undoes the last edit.
198
mEditor <- setRefClass("matrixEditor",
56211 maechler 199
        fields = list(data = "matrix",
200
		     edits = "list"),
201
       methods = list(
53068 jmc 202
     edit = function(i, j, value) {
203
       ## the following string documents the edit method
204
       'Replaces the range [i, j] of the
56211 maechler 205
	object by value.
53068 jmc 206
        '
207
         backup <-
208
             list(i, j, data[i,j])
209
         data[i,j] <<- value
210
         edits <<- c(list(backup),
211
                     edits)
212
         invisible(value)
213
     },
214
     undo = function() {
215
       'Undoes the last edit() operation
216
        and update the edits field accordingly.
217
        '
218
         prev <- edits
219
         if(length(prev)) prev <- prev[[1]]
220
         else stop("No more edits to undo")
221
         edit(prev[[1]], prev[[2]], prev[[3]])
222
         ## trim the edits list
223
         length(edits) <<- length(edits) - 2
224
         invisible(prev)
225
     }
226
     ))
227
xMat <- matrix(1:12,4,3)
61035 jmc 228
xx <- mEditor(data = xMat)
53068 jmc 229
xx$edit(2, 2, 0)
230
xx$data
231
xx$undo()
232
mEditor$help("undo")
233
stopifnot(all.equal(xx$data, xMat))
234
 
235
## add a method to save the object
236
mEditor$methods(
237
     save = function(file) {
238
       'Save the current object on the file
59654 jmc 239
 in R external object format.
240
'
53068 jmc 241
         base::save(.self, file = file)
59654 jmc 242
     },
243
     counter = function(i) {
244
         'The number of items in the i-th edit.
245
 (Used to test usingMethods())
246
'
247
         if(i > 0 && i <= length(edits))
248
             length(edits[[i]][[3]])
249
         else
250
             0L
53068 jmc 251
     }
252
)
253
 
254
tf <- tempfile()
255
xx$save(tf) #$
256
load(tf)
257
unlink(tf)
258
stopifnot(identical(xx$data, .self$data))
259
 
62700 jmc 260
## tests of $trace() methods
261
## debugging an object
262
xx$trace(edit, quote(xxTrace <<- TRUE))
263
 
264
## debugging all objects from class mEditor in method $undo()
265
mEditor$trace(undo, quote(mETrace <<- TRUE))
266
 
267
xxTrace <- mETrace <- FALSE
268
xx$edit(2,3,100)
269
xx$undo()
270
 
271
## will not have changed the xx$undo() method (already used)
272
stopifnot(identical(xxTrace, TRUE), identical(mETrace, FALSE))
273
 
274
## but a new object works the other way around
275
xxTrace <- mETrace <- FALSE
276
xx <- mEditor(data = xMat)
277
xx$edit(2,3,100)
278
xx$undo()
279
stopifnot(identical(xxTrace, FALSE), identical(mETrace, TRUE))
280
 
281
 
282
 
53068 jmc 283
markViewer <- ""
284
setMarkViewer <- function(what)
285
    markViewer <<- what
286
 
287
## Inheriting a reference class:  a matrix viewer
288
mv <- setRefClass("matrixViewer",
289
    fields = c("viewerDevice", "viewerFile"),
290
    contains = "matrixEditor",
291
    methods = list( view = function() {
292
        dd <- dev.cur(); dev.set(viewerDevice)
293
        devAskNewPage(FALSE)
294
        matplot(data, main = paste("After",length(edits),"edits"))
295
        dev.set(dd)},
296
        edit = # invoke previous method, then replot
297
          function(i, j, value) {
298
            callSuper(i, j, value)
299
            view()
300
          }))
301
 
302
## initialize and finalize methods
53470 jmc 303
mv$methods( initialize = function(file = "./matrixView.pdf", ...) {
304
    viewerFile <<- file
53068 jmc 305
    pdf(viewerFile)
306
    viewerDevice <<- dev.cur()
307
    message("Plotting to ", viewerFile)
308
    dev.set(dev.prev())
309
    setMarkViewer("ON")
310
    initFields(...)
311
  },
312
  finalize = function() {
313
    dev.off(viewerDevice)
314
    setMarkViewer("OFF")
315
  })
316
 
59654 jmc 317
## a counts method to test usingMethods()
318
mv$methods( counts = function() {
319
    usingMethods("counter")
320
    sapply(seq_along(edits), "counter")
321
})
322
 
323
 
61035 jmc 324
ff <- mv( data = xMat)
53068 jmc 325
stopifnot(identical(markViewer, "ON")) # check initialize
326
ff$edit(2,2,0)
327
ff$data
69213 ripley 328
if(methods:::.hasCodeTools())  # otherwise 'counter' is not visible
329
    stopifnot(identical(ff$counts(), length(ff$edits[[1]][[3]])))
53068 jmc 330
ff$undo()
331
stopifnot(all.equal(ff$data, xMat))
332
rm(ff)
333
gc()
334
stopifnot(identical(markViewer, "OFF")) #check finalize
53212 jmc 335
 
53669 jmc 336
## tests of copying
337
viewerPlus <- setRefClass("viewerPlus",
338
                   fields = list( text = "character",
339
                      viewer = "matrixViewer"))
61035 jmc 340
ff <- mv( data = xMat)
341
v1 <- viewerPlus(text = letters, viewer = ff)
53669 jmc 342
v2 <- v1$copy()
343
v3 <- v1$copy(TRUE)
344
v2$text <- "Hello, world"
345
v2$viewer$data <- t(xMat) # change a field in v2$viewer
346
v3$text <- LETTERS
61035 jmc 347
v3$viewer <- mv( data = matrix(nrow=1,ncol=1))
53669 jmc 348
## with a deep copy all is protected, with a shallow copy
349
## the environment of a copied field remains the same,
350
## but replacing the whole field should be local
351
stopifnot(identical(v1$text, letters),
352
          identical(v1$viewer, ff),
353
          identical(v2$text, "Hello, world"))
354
v3 <- v1$copy(TRUE)
355
v3$viewer$data <- t(xMat) # should modify v1$viewer as well
356
stopifnot(identical(v1$viewer$data, t(xMat)))
357
 
53693 jmc 358
## the field() method
359
stopifnot(identical(v1$text, v1$field("text")))
360
v1$field("text", "Now is the time")
361
stopifnot(identical(v1$field("text"), "Now is the time"))
362
 
363
## setting a non-existent field, or a method, should throw an error
364
stopifnot(is(tryCatch(v1$field("foobar", 0), error = function(e)e), "error"),
365
         is(tryCatch(v1$field("copy", 0), error = function(e)e), "error") )
366
 
53669 jmc 367
## the methods to extract class definition and generator
53693 jmc 368
stopifnot(identical(v3$getRefClass()$def, getRefClass("viewerPlus")$def),
369
          identical(v3$getClass(), getClass("viewerPlus")))
53669 jmc 370
 
53212 jmc 371
## deal correctly with inherited methods and overriding existing
372
## methods from $methods(...)
373
refClassA <- setRefClass("refClassA", methods=list(foo=function() "A"))
374
refClassB <- setRefClass("refClassB", contains="refClassA")
375
mnames <- objects(getClass("refClassB")@refMethods)
376
refClassB$methods(foo=function() callSuper())
61035 jmc 377
stopifnot(identical(refClassB()$foo(), "A"))
53212 jmc 378
mnames2 <- objects(getClass("refClassB")@refMethods)
379
stopifnot(identical(mnames2[is.na(match(mnames2,mnames))], "foo#refClassA"))
380
refClassB$methods(foo=function() paste(callSuper(), "Version 2"))
61035 jmc 381
stopifnot(identical(refClassB()$foo(), "A Version 2"))
53212 jmc 382
stopifnot(identical(mnames2, objects(getClass("refClassB")@refMethods)))
53274 jmc 383
 
384
if(methods:::.hasCodeTools()) {
54575 jmc 385
    ## code warnings assigning locally to field names
56211 maechler 386
    stopifnot(is(tryCatch(mv$methods(test = function(x)
387
                                 { data <- x[!is.na(x)]; mean(data)}),
388
                          warning = function(e)e), "warning"))
53274 jmc 389
 
54575 jmc 390
    ## warnings for nonlocal assignment that is not a field
391
    stopifnot(is(tryCatch(mv$methods(test2 = function(x) {something <<- data[!is.na(x)]}), warning = function(e)e), "warning"))
392
 
393
    ## error for trying to assign to a method name
394
    stopifnot(is(tryCatch(mv$methods(test3 = function(x) {edit <<- data[!is.na(x)]}), error = function(e)e), "error"))
53274 jmc 395
} else
396
    warning("Can't run some tests:  recommended package codetools is not available")
53330 jmc 397
 
398
## tests (fragmentary by necessity) of promptClass for reference class
53470 jmc 399
ccon <- textConnection("ctxt", "w")
400
suppressMessages(promptClass("refClassB", filename = ccon))
53330 jmc 401
## look for a method, inheritance, inherited method
402
stopifnot(length(c(grep("foo.*refClassA", ctxt),
403
                   grep("code{foo()}", ctxt, fixed = TRUE),
404
                   grep("linkS4class{refClassA", ctxt, fixed = TRUE))) >= 3)
53470 jmc 405
close(ccon)
53330 jmc 406
rm(ctxt)
53382 jmc 407
 
408
 
409
## tests related to subclassing environments.  These really test code in the core, viz. builtin.c
61035 jmc 410
a <- refClassA()
53382 jmc 411
ev <- new.env(parent = a) # parent= arg
412
stopifnot(is.environment(ev))
413
foo <- function()"A"; environment(foo) <- a # environment of function
414
stopifnot(identical(as.environment(a), environment(foo)))
415
xx <- 1:10; environment(xx) <- a # environment attribute
416
stopifnot(identical(as.environment(a), environment(xx)))
417
 
418
 
56211 maechler 419
## tests of [[<- and $<- for subclasses of environment.  At one point
420
## methods for these assignments were defined and caused
421
## inf. recursion when the arguments to the [[<- case were changed in base.
53385 jmc 422
setClass("myEnv", contains = "environment")
53641 jmc 423
m <- new("myEnv", a="test")
424
m2 <- new("myEnv"); m3 <- new("myEnv")
425
## test that new.env() is called for each new object
426
stopifnot(!identical(as.environment(m), as.environment(m2)),
427
          !identical(as.environment(m3), as.environment(m2)))
53385 jmc 428
m[["x"]] <- 1; m$y <- 2
56211 maechler 429
stopifnot(identical(c(m[["x"]], m$y), c(1,2)), is(m, "myEnv"))
53641 jmc 430
rm(x, envir = m) # check rm() works, does not clobber class
431
stopifnot(identical(sort(objects(m)), sort(c("a", "y"))),
432
          is(m, "myEnv"))
53465 jmc 433
 
53564 jmc 434
## tests of binding & environment tools with subclases of environment
435
lockBinding("y", m)
436
stopifnot(bindingIsLocked("y", m))
437
unlockBinding("y", m)
438
stopifnot(!bindingIsLocked("y", m))
439
 
440
makeActiveBinding("z", function(value) {
441
    if(missing(value))
442
        "dummy"
443
    else
444
        "dummy assignment"
445
}, m)
446
stopifnot(identical(get("z", m),"dummy"))
447
## assignment will return the value but do nothing
448
stopifnot(identical(assign("z","other", m), "other"),
449
          identical(get("z", m),"dummy"))
450
 
451
 
452
## this has to be last--Seems no way to unlock an environment!
453
lockEnvironment(m)
454
stopifnot(environmentIsLocked(m))
455
 
53645 maechler 456
rm(m)
457
m <- new("myEnv")
458
stopifnot(length(ls(m)) == 0)
459
## used to contain the previous content
53564 jmc 460
 
53645 maechler 461
 
53465 jmc 462
## test of callSuper() to a hidden default method for initialize() (== initFields)
463
TestClass <- setRefClass ("TestClass",
53470 jmc 464
     fields = list (text = "character"),
465
     methods = list(
466
       print = function ()  {cat(text)},
467
       initialize = function(text = "", ...) callSuper(text = paste(text, ":", sep=""),...)
468
  ))
61035 jmc 469
tt <- TestClass("hello world")
53470 jmc 470
stopifnot(identical(tt$text, "hello world:"))
471
## now a subclass with another field & another layer of callSuper()
472
TestClass2 <- setRefClass("TestClass2",
473
        contains = "TestClass",
474
        fields = list( version = "integer"),
475
        methods = list(
56572 jmc 476
          initialize = function(..., version = 0L)
477
              callSuper(..., version = version+1L))
53470 jmc 478
  )
61035 jmc 479
tt <- TestClass2("test", version = 1L)
53470 jmc 480
stopifnot(identical(tt$text, "test:"), identical(tt$version, as.integer(2)))
61035 jmc 481
tt <- TestClass2(version=3L) # default text
53470 jmc 482
stopifnot(identical(tt$text, ":"), identical(tt$version, as.integer(4)))
54575 jmc 483
 
484
 
55779 jmc 485
## test some capabilities but read-only for .self
486
.changeAllFields <- function(replacement) {
487
    fields <- names(.refClassDef@fieldClasses)
488
    for(field in fields)
489
        eval(substitute(.self$FIELD <- replacement$FIELD,
490
                        list(FIELD = field)))
491
}
492
 
493
mEditor$methods(change = .changeAllFields)
61035 jmc 494
xx <- mEditor(data = xMat)
55779 jmc 495
xx$edit(2, 2, 0)
496
 
61035 jmc 497
yy <- mEditor(data = xMat+1)
55779 jmc 498
yy$change(xx)
499
stopifnot(identical(yy$data, xx$data), identical(yy$edits, xx$edits))
500
 
501
## but don't allow assigment
502
if(methods:::.hasCodeTools())
503
        stopifnot(is(tryCatch(yy$.self$data <- xMat, error = function(e)e), "error"))
55988 jmc 504
 
61058 jmc 505
## the locked binding of refGeneratorSlot class should prevent modifying
55988 jmc 506
## methods, locking fields or setting accessor methods
61058 jmc 507
## Nothing special about refGeneratorSlot in this test -- the point is just
508
## to use a standard reference class known to be defined in a package
509
evr <- getRefClass("refGeneratorSlot") # in methods
55988 jmc 510
stopifnot(is(tryCatch(evr$methods(foo = function()"..."), error = function(e)e), "error"),
511
         is(tryCatch(evr$lock("def"), error = function(e)e), "error"),
512
         is(tryCatch(evr$accessors("def"), error = function(e)e), "error"))
56119 jmc 513
 
514
##getRefClass() method and function should work with either
515
## a class name or a class representation (bug report 14600)
516
tg <- setRefClass("tg", fields = "a")
61035 jmc 517
t1 <- tg(a=1)
56119 jmc 518
tgg <- t1$getRefClass()
519
tggg <- getRefClass("tg")
520
stopifnot(identical(tgg$def, tggg$def),
521
          identical(tg$def, tgg$def))
522
 
57841 jmc 523
## this used to fail in initFieldArgs() from partial matching "self"
524
selfClass <- setRefClass("selfClass",
525
        fields=list(
526
            self="character", super="character", sub="character"
527
        )
528
    )
529
 
61035 jmc 530
stopifnot(identical(selfClass(self="B", super="A", sub="C")$self, "B"))