Defining return values of the same class in interface implementations

hello,

i'm trying to update older code to java 1.5 using generics. i'm new to generics and i have a problem i cannot solve: assuming the interface

publicinterface Stake

{

public Stake makeACopyAndShift(long delta );

}

and the class

publicclass BasicStake

{

privatefinallong pos;

public BasicStake(long pos )

{

this.pos = pos;

}

public Stake makeACopyAndShift(long delta )

{

returnnew BasicStake( pos + delta );

}

}

... and a container class Trail:

publicclass Trail<S>{

privatefinal List<S> stakes =new ArrayList<S>();

public Trail(){}

publicvoid add( S stake ){ stakes.add( stake );}

public S get(int index ){return stakes.get( index );}

publicvoid shiftAll(long delta )

{

final List<S> stakesNew =new ArrayList<S>( stakes.size() );

S orig, copy;

for(int i = 0; i < stakes.size(); i++ ){

orig = stakes.get( i );

copy = (S) orig.makeCopyAndShift( delta );

stakesNew.add( copy );

}

stakes.clear();

stakes.addAll( stakesNew );

}

}

so that i could do:

Trail<BasicStake> t =new Trail<BasicStake>();

etc.

how do i manage to get rid of the warning

"Type safety: The cast from Stake to S is actually checking against the erased type Stake"

with casting to (S) in the for-loop in the shiftAll function? Obviously the problem is that in interface Stake the return type of makeCopyAndShift should not be Stake but "<SameClassAsMe>", so that in BasicStake the method would be

public BasicStake makeCopyAndShift(long delta ){ ...}

. how do i accomplish that?

thanks a lot!

ciao, -sciss-

[3593 byte] By [itemStateChangeda] at [2007-11-27 10:42:52]
# 1

Something like this if I'm not mistaken:

public class Trail<S extends Stake> {

private final List<Stake> stakes;

public Trail() { stakes = new ArrayList<Stake>(); }

public void add(S stake) { stakes.add(stake); }

public Stake get(int index) { return stakes.get(index); }

public void shiftAll(long delta) {

final List<Stake> stakesNew = new ArrayList<Stake>(stakes.size());

for(int i = 0; i < stakes.size(); i++ ) {

Stake orig = stakes.get(i);

Stake copy = orig.makeACopyAndShift(delta);

stakesNew.add(copy);

}

stakes.clear();

stakes.addAll(stakesNew);

}

}

prometheuzza at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 2

but the whole idea is to be dealing with special cases of Stake, so i definitely want

private final List<S> stakes;

and

public S get( int index ) { return stakes.get( index ); }

... otherwise there's no point in using generics.

itemStateChangeda at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 3

This seems to work just fine for me:

public class Foo {

public static void main(String[] args) {

Trail<Stake> trail = new Trail<Stake>();

trail.add(new BasicStake(1));

trail.add(new AnotherStake(1));

trail.shiftAll(10);

}

}

interface Stake {

public Stake makeACopyAndShift(long delta);

}

class BasicStake implements Stake {

private final long pos;

public BasicStake(long pos) {

this.pos = pos;

}

public Stake makeACopyAndShift(long delta) {

return new BasicStake(pos+delta);

}

}

class AnotherStake implements Stake {

private final long pos;

public AnotherStake(long pos) {

this.pos = pos;

}

public Stake makeACopyAndShift(long delta) {

return new AnotherStake(pos*delta);

}

}

class Trail<S extends Stake> {

private final List<Stake> stakes;

public Trail() { stakes = new ArrayList<Stake>(); }

public void add(S stake) { stakes.add(stake); }

public Stake get(int index) { return stakes.get(index); }

public void shiftAll(long delta) {

final List<Stake> stakesNew = new ArrayList<Stake>(stakes.size());

for(int i = 0; i < stakes.size(); i++ ) {

Stake orig = stakes.get(i);

Stake copy = orig.makeACopyAndShift(delta);

stakesNew.add(copy);

}

stakes.clear();

stakes.addAll(stakesNew);

}

}

prometheuzza at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 4

but

Trail<Stake> trail = new Trail<Stake>();

doesn't make sense, i wouldn't need generics to do that. this will not work:

Trail<BasicStake> trail = new Trail<BasicStake>();

trail.add( new BasicStake( 1 ));

BasicStake x = trail.get( 0 );// > fails

itemStateChangeda at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 5

> but

>

> Trail<Stake> trail = new Trail<Stake>();

>

> doesn't make sense, i wouldn't need generics

> to do that. this will not work:

>

> Trail<BasicStake> trail = new Trail<BasicStake>();

> trail.add( new BasicStake( 1 ));

> BasicStake x = trail.get( 0 );// > fails

Ah yes, I see what you mean.

What I do know is that you should bound that S in your Trail class so that it is a Stake.

I'm sure there will be someone along that knows some Java-generics (unlike me!).

; )

prometheuzza at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 6

Why don't you do some work yourself and adapt what's there?class Trail<S extends Stake> {

private final List<S> stakes;

public Trail() { stakes = new ArrayList<S>(); }

public void add(S stake) { stakes.add(stake); }

public S get(int index) { return stakes.get(index); }

public void shiftAll(long delta) {

final List<S> stakesNew = new ArrayList<S>(stakes.size());

for(int i = 0; i < stakes.size(); i++ ) {

S orig = stakes.get(i);

S copy = orig.makeACopyAndShift(delta);

stakesNew.add(copy);

}

stakes.clear();

stakes.addAll(stakesNew);

}

}

Where "makeACopyAndShift" should return the proper type (co-variant return).

stefan.schulza at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 7

thank you, i didn't know overriding return values in implementing classes was allowed (what you coin "co-variant return"), that seems to be exactly what i need.

ciao, -sciss-.

itemStateChangeda at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 8

> thank you, i didn't know overriding return values in

> implementing classes was allowed (what you coin

> "co-variant return"), that seems to be exactly what i

> need.

Ah, OK. So your OP was a case of information overflow wrt. the actual problem. :)

stefan.schulza at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 9

Can you complete the example? It is not clear to me how to utilize covariant return in this case. I have the following solution which works with the Trail class provided, but I think you mean something different.

interface Stake<S> {

public S makeACopyAndShift(long delta);

}

class BasicStake implements Stake<BasicStake> {

...

public BasicStake makeACopyAndShift(long delta) {

return new BasicStake(pos + delta);

}

}

szhigunova at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 10

Actually in my solution I had to change Trail class. It looks like this:

interface Stake<S> {

public S makeACopyAndShift(long delta);

}

class BasicStake implements Stake<BasicStake> {

private final long pos;

public BasicStake(long pos) {

this.pos = pos;

}

public BasicStake makeACopyAndShift(long delta) {

return new BasicStake(pos + delta);

}

}

class Trail<S extends Stake><S>> {

private final List<S> stakes;

public Trail() { stakes = new ArrayList<S>(); }

public void add(S stake) { stakes.add(stake); }

public S get(int index) { return stakes.get(index); }

public void shiftAll(long delta) {

final List<S> stakesNew = new ArrayList<S>(stakes.size());

for(int i = 0; i < stakes.size(); i++ ) {

S orig = stakes.get(i);

S copy = orig.makeACopyAndShift(delta);

stakesNew.add(copy);

}

stakes.clear();

stakes.addAll(stakesNew);

}

}

szhigunova at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 11

No generics involved with co-variant return.

interface Stake { // no generics here!

public Stake makeACopyAndShift(long delta);

}

class BasicStake implements Stake {

...

public BasicStake makeACopyAndShift(long delta) {

return new BasicStake(pos + delta);

}

}

stefan.schulza at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...
# 12

I am sorry, but I still do not understand how it all plays together. What about generic Trail class?

szhigunova at 2007-7-28 19:21:05 > top of Java-index,Core,Core APIs...