0

What's the best way to enforce that an S4 object is always created with arguments, meaning that the default constructor can never be called?

rimorob
  • 624
  • 1
  • 5
  • 16
  • It's not really clear what 'always' means (e.g., it's possible to invoke the first two lines of `new()`, avoiding the `initialize()` method), or what your use case is; users seem quite creative in avoiding conventions or best practices. – Martin Morgan Jan 02 '15 at 17:41
  • I want to prevent the syntax new('MyClass') from being used when the right syntax is new('MyClass', a='a', b='b') – rimorob Jan 02 '15 at 18:58

2 Answers2

1

I think the user doesn't want to use new(), but rather a function for which you can specify arguments / hints and provide documentation; ideally the user has no notion that they're using 'S4 classes', just invoking some function that returns an object that they can invoke other functions on. My preferred approach is

.A = setClass("A", representation=representation(x="numeric"))
A = function(x=numeric(), ...) {
    ## user-friendly coercion / checks / etc to 'x'
    .A(x=x, ...)
}
## accessors and other methods

Export only A() in the package NAMESPACE. Since an implicit requirement of S4 classes is that in fact validObject(new("A")) evaluates to TRUE (e.g., from earlier today), it seems difficult to avoid allowing the user to construct the class in this way.

Community
  • 1
  • 1
Martin Morgan
  • 45,935
  • 7
  • 84
  • 112
  • This seems like an unfortunate kludge in the style of R kludges. Let's have (poor, hash-based) OO, but let's hide it from the user and have them think there's no typing under the hood. This is what I was doing, of course. Isn't there a way to do what I want using 'initialize'? – rimorob Jan 05 '15 at 22:15
  • @rimorob No, since `new("A")` has to work, `initialize()` has to work -- there's no room for passing secret messages. – Martin Morgan Jan 06 '15 at 00:21
0

It would appear that creating an explicit 'initialize' method with arguments DOES prevent a new('MyType') call without parameters from being accepted. It seems that this was the solution I was looking for.

rimorob
  • 624
  • 1
  • 5
  • 16