My wishlist for (200|JDK)7
December 23rd, 2006Combined Types
I’d like to declare a method that requires an Object implementing more than one interface, just a shorthand for
interface MyMethodsRequiredParameter extends Intf1,Intf2 {};
foo(MyMethodsRequiredParameter bar);
This can be done with generics (kudos to Ricky! ):
<MyMethodsRequiredParameter extends Intf1 & Intf2>foo(MyMethodsRequiredParameter bar);
Well, a bit shorter syntax would be nice:
foo(Intf1&Intf2 bar);
The reversed problem is the creation, it can be done via java.lang.reflect.Proxy but it is tedious, so why not
Intf1&Intf2 myMethodsRequiredParameter = new Object() implements Intf1,Intf2 {…};
Limiting Interfaces & Views
When integrating third-party code you just simply don’t want to take all of it, so you wrap it to expose on that part of the interfaces you need. So I want to say
view MyList as java.util.Collection{
int size() = java.util.Collection.size();
}
To use just one method from Collection. The effect was as if Collection would implement
interface MyList {
int size();
}
The problem with a stand-alone interface is that size() there is not the same (java.lang.reflect.)Method and so I have to wrap the whole API by delegation
class StupidList implements MyList {
final private Collection coll = new ArrayList();
public int size() { return coll.size() }
}
And I do not only have to wrap the types, also write façades for the whole API because MyList is not a Collection… you get the point: Hundreds or thousands of line of stupid code that do virtually nothing.
More advanced
view Iterator as java.util.Enumeration {
bool hasNext() = java.util.Enumeration.hasNextElement();
Object next() = java.util.Enumeration.nextElement();
}
or
view StupidList implements MyList as ArrayList {
public int size() = ArrayList.size();
}
The important difference to the delegation is that StupidList stays an ArrayList it is only that the type ArrayList is hidden. Views need to co-exist:
view StupidList implements MyList as HashMap {
public int size() = Map.size();
}
So both types HashMap and ArrayList use a common “interface”, the only restriction is that views (nor their subclasses) can never be instanciated.
Another very useful application of views is implicit conversion
view Integer as Double{
Integer(){
if (doubleValue()>Integer.MAX) throw new IllegalArgumentException();
if (doubleValue()
}
double doubleValue()=Double.doubleValue();
int intValue() = Math.round(doubleValue());
}
This view does two things at once: It checks if the value is OK for an int and redefines the conversion. With this view this code
foo(Double dd) {
Integer ii = d;
is equivalent to
foo(Double dd) {
if (dd.doubleValue()>Integer.MAX) throw new IllegalArgumentException();
if(dd.doubleValue()
Integer ii = Integer.valueOf(Math.round(dd.doubleValue());
In fact not entirely. With the view ii stays a Double that just looks like an Integer. This is more important for mutable objects where the original object gets manipulated via the interface of another type! Views are also a better cast method, as they are not casting but dynamically inject the requested interface.
Perhaps views are also an alternative to type inference. Imagine I could simply say
boolean notEmpty(T[] someArray)
MyList list = Collections.asList(someArray);
return list.size()>0;
}
The declaration is not so difficult and barely redundant. I declare a MyList because this is what I need. The view logic wraps the concrete type I will receive so I don’t have to figure out what will be the type return from the expresion on the right.
Technical issues
The view idea had been borrowed from Scala. There the conversions are controlled by implicit parameter that are visible in the scope of the invocation. I am not sure if this would be the right idea for Java. Where should we put a declaration for the view Integer. The Java convention is to place a top-level object in a file of the same name. Java.lang.Integer is already taken and injecting such a powerful feature outside the package will compromise security. Super-packages (JSR 294) might help to solve this problem as view will be the killer application for the superpackages.
Methods as first-class objects
This is an extension to the closure proposal that seems to be sure to come for JDK 7
class Mine {
public void doit() {
…
}
}
foo(Mine mine) {
call({=>mine.doit()});
}
call({Mine.doit()} func) {
func();
}
This is very close to Closures. Closures are indeed a way of implementing it:
call({=>Void} func);
would work fine but would accept any void function with no parameters. On the other hand declaration referencing a concrete method is of limited use as it could be replaced by
callDoit(mine)
as the method is fully fixed; on the other hand this exposes the entire object, also calling static methods simply does not work that way. The real power of methods being first-class is meta programming:
class CanDo {
CanDo({Mine.doit()} func) {
{this.doit()} = func;
{this.doThat()} = func;
}
abstract final void doit(); //abstract final-> ctor provides implementation
volatile void doThat() {}; //volatile method: implementation can be changed
}
with closures:
class CanDo {
private final {=>Void} thisFunc;
private {=>Void} thatFunc = {=>null};
CanDo({=>Void} func) {
thisFunc = func;
thatFunc = func;
}
final void doit(){thisFunc()};
void doThat() {thatFunc()};
}
Closures are a bit more verbose and we cannot declare “the quality” of the method (e.g. which interface declared it).
More from Closures
Any method should be allowed to declared its return type to be Unreachable, this allows to write “exit methods”:
class Foo {
Unreachable throwException() throws RuntimeException {
RuntimeException re;
// form here a nice exeption object
throw re;
}
int bar1() {
throwException(); //Today an error!
}
}

