Two recent changes have been committed to r-devel, related to
discussions on this list earlier:
1. setOldClass() has an argument prototype= to specify the default
object for the class. If provided, the S3 class can be a slot in an S4
class, with a valid default object.
(It's still not going to work well to have an S3 non-virtual class as a
superclass of an S4 class. See the setOldClass help page.)
2. There is a heuristic test for S4 objects, seemsS4Object(), and a
corresponding C-level test, R_seemsS4Object(object), both using the
existence of a "package" attribute on class(object) as a test.
The test is called seemsS4Object() rather than isS4Object()
deliberately, but it should be fairly accurate.
It will mistakenly identify an S3 object as S4 if the package attribute
is there (possible, but hard to see why anyone would do this).
It can make the opposite mistake, though, UNLESS the package generating
the object is reinstalled with the current version of R, because older
versions failed to put the attribute on some of the basic S4 classes
This is not by itself the right test for intercepting S3 code for
certain primitives (c(), match(), [, for example), as was being
discussed earlier. Only S4 objects that do not inherit from "vector"
should be blocked. So the suitable test, in R code, is something like:
if(seemsS4Object(x) && !is(x, "vector"))