The choices are:
---- ONE ----
@SingleImpl
interface Person {
String getName();
}
class JsoPerson extends JavaScriptObject implements Person { ... }
// It is an error to define any other type that implements Person,
including anonymous types
// subclassing JsoPerson is OK
---- TWO ----
@SingleJsoImpl
interface Person {
String getName();
}
class JsoPerson extends JavaScriptObject implements Person { ... }
// It is an error to define any other JSO type that implements Person
// subclassing JsoPerson is OK
class RegularPerson implements Person { ... }
(new Person() { ... })
// But you can have as many non-JSO types implementing Person
Tradeoffs:
- Scenario one is more restrictive, but calling ((Person)
x).getName() can always be statically resolved to one method
- Land-mines with anonymous types
- Scenario two allows a JSO implementation to inter-operate with regular code
- Only land-mine would be in declaring a second JSO type
- ((Person) x).getName() would be more expensive to dispatch if
type-tightening doesn't occur; modulo optimizations, it would look
like "x.typeId$ ? x.getName() : getName$(x)"
- This dispatch penalty applies only to interfaces with a JSO
implementation and one or more regular implementations and
type-tightening occurs.
- Would be doing polymorphic dispatch anyway, this just adds a
ternary expression
I'm favoring scenario two because it provides the developer
significant additional flexibility. Consider the following where you
get a payload from the server in JSON format, but also want to edit
some of the resulting objects.
@SingleJsoImpl
interface Person {
String getName();
}
final class JsoPerson extends JavaScriptObject implements Person {
protected JsoPerson() {}
public native String getName() /*-{ return this.name; }-*/;
}
class MutablePerson implements Person {
private String name;
public MutablePerson(Person copyFrom) {this.person = copyFrom.getName();}
public String getName() {return name;}
public void setName(String name);
}
--
Bob Vawter
Google Web Toolkit Team
Does anyone buy that reasoning? An important related question is whether these things are actually compiler flags or whether they are module settings. I think they are actually more appropriate as the latter.
On Wed, Jan 7, 2009 at 10:48 AM, Bruce Johnson <br...@google.com> wrote:If they are module flags, what happens when you have different settings for different modules (as you point out, it will be impossible to keep them consistent in a large code base with shared code)?Does anyone buy that reasoning? An important related question is whether these things are actually compiler flags or whether they are module settings. I think they are actually more appropriate as the latter.
If it is a compile-time error, then some code simply won't be shareable between projects -- maybe that is ok if that module's owner has decided it is important enough to set the flag in a library module? If it is based on which module it is in, does the caller or callee win the battle, and will that behavior be surprising to a developer?
There's another advantage to option 2: the Java implementations of the
interface will exist anyway, and this flexibility will mean it doesn't
cause a problem if those classes are added to the web-mode compile.
This can happen late during maintenance, and without option 2,
SingleImpl would force them into a larger refactor.
So, belatedly, +1 for option 2. The flexibility isn't just at initial
design time.
Lex