|
Replies:
4
-
Last Post:
May 4, 2006 7:20 AM
by: kfgodel
|
|
|
|
|
|
|
Generic "this" ("self") method return type
Posted:
Jan 28, 2005 10:45 AM
|
|
|
Could we have way of declaring method return type to be its current (mplementation) subclass. Then calls on subclass instance could be easily chained.
Current way is to have override a method with its current class as return type. It calls parent method, and then returns this :
class Base {
protected final void setDo( Object key, Object value ) { /*do-what-told*/ }
public Base set( Object key, Object value ) { setDo( old, value ); return this; }
}
class Child extends Base {
public Child set( Object key, Object value ) { setDo( key, value ); return this; }
protected final void setSeveral( Map pairs ) {
for( final Map.Entry entry : pairs.entrySet() ) {
set( entry.getKey(), entry.getValue() );
}
}
public Child setSeveral( Map pairs ) {
setDo( pairs );
return this;
}
}
This allows subclass to have new methods added, while both inherited and own methods can be called in chain (like StringBuffer):
new Child().set( "name", "Happy" ).set( mapOfKeyValuePairsToSet ).set( "description", "Friend" );
However, that makes subclasses have non-creative Xyz(...)methods, which just: 1. narrow down return type, so that chained calls to own methods are possible 2. call parent XyzDo(...) method 3. return this
That makes subclasses: 1. awkward 2. pottentially out-of-contract, because child method can process additional/different code that just calling parent method and returning this
Above could be healed if there were a possibility to defined method return type to be "generic this", ie its current implementation class type. If we use <~> notation here, it would look like:
class Base {
public final <~> set( Object key, Object value ) {
/*do-what-told*/
return this;
}
}
class Child extends Base {
public final <~> setSeveral( Map pairs ) {
for( final Map.Entry entry : pairs.entrySet() ) {
set( entry.getKey(), entry.getValue() );
}
return this;
}
}
/* Then: */
new Child().set( "name", "Smiling" ).setSeveral( map );
I'm not sure how Javac and JVM would implement this. Maybe create a "shadow" void setSelfGeneric(Object,Object) method, and then create a bridge method to it in any subclass, which just calls it, and returns this.
If user were allowed to return a different Object than this, ie another Object of the same class as implementation, then it would need to check the type in runtime.
Interfaces could declare Self-Return method types as well.
Not sure whether Self-Return methods should be allowed not to be final (except when they're abstract). If subclass might change the behavior, then final Self-Return method can call a non-final protected method to do the job.
|
|
|
|
|
|
|
Re: Generic "this" ("self") method return type
Posted:
Jan 28, 2005 12:51 PM
in response to: peterkehl
|
|
|
It would also clarify behavior of Object.getClass(), which must have special support of compiler, as its Javadoc says:
"Returns:
The java.lang.Class object that represents the runtime class of the object. The result is of type Class<? extends X> where X is the erasure of the static type of the expression on which getClass is called."
|
|
|
|
|
|
|
|
Re: Generic "this" ("self") method return type
Posted:
Jan 29, 2005 4:28 PM
in response to: peterkehl
|
|
|
You can do some similar with only 1.5 facilities. Give the base class a generic parameter that represents a type "like this". Either cast this, or return the return value of an abstract "get this"/self method.
public abstract class Base<THIS extends Base> { private int x; private int y; @SuppressWarnings("unchecked") public THIS location(int x, int y) { this.x = x; this.y = y; return (THIS)this; } } public class Concrete extends Base<Concrete> { }
Or
public abstract class Base<THIS extends Base> { private int x; private int y; protected Base() { assert this == getThis(); } public abstract THIS getThis(); public THIS location(int x, int y) { this.x = x; this.y = y; return getThis(); } } public class Concrete extends Base<Concrete> { public Concrete getThis(); return this; } }
I must admit, I've only tried it once and didn't like it much in that particular situation.
Personally, I'd prefer a notation that allows a chain of method invocations on a single expression.
|
|
|
|
|
|
|
|
Thx: Generic "this" ("self") method return type
Posted:
Jan 31, 2005 5:30 AM
in response to: tackline
|
|
|
Thank you, Tackline.
It perfectly does the job.
|
|
|
|
|
|
|
|
Re: Thx: Generic "this" ("self") method return type
Posted:
May 4, 2006 7:20 AM
in response to: peterkehl
|
|
|
Even though passing the concrete class in a type variable can fix your problem, I think it is cumbersome. Imagine passing by type parameter an already parametrized class. Your typing can grow exponentially, and your clarity become null very quickly. I still think that a way of saying something like "this" for the actual concrete type is necessary and serves the clarity of expressions in the language
|
|
|
|
|