abstract sclass Either { bool isA() { false; } bool isB() { false; } A a() { throw _failMe(); } B b() { throw _failMe(); } A aOpt() { null; } B bOpt() { null; } RuntimeException _failMe() { fail("Either object is of wrong type: " + shortClassName(value)); } toString { ret "Either" + (isA() ? "A" : "B") + "(" + value + ")"; } } sclass EitherA extends Either { A value; bool isA() { true; } A a() { ret value; } A aOpt() { ret value; } } sclass EitherB extends Either { B value; bool isB() { true; } B b() { ret value; } B bOpt() { ret value; } }