简体   繁体   中英

Java, generics and static methods

I would like to have a generic Interpolator class which can interpolate between instances of classes implementing the Interpolatable interface:

interface Interpolatable {
  int getDimension();
  Iterator <? extends Interpolatable> getIterator(double d);
}

class Coordinate extends AnotherClass implements Interpolatable  {
  public int getDimension() {return 3;}
  public Iterator <Coordinate> getIterator (double d) {…}
}

class Interpolator <T extends Interpolatable> {
  Interpolator () {
    int dim = T.getDimension();
  }
  void doSomething (double d) {
    Iterator <? extends Interpolatable> it = T.getIterator(d);
    Interpolatable t = it.next();
    …
  }
}

Of course, the compiler complains about T.getDimension() and T.getIterator(d) :

Cannot make a static reference to the non-static method getDimension()/getIterator(double) from the type Interpolatable.

However, the two methods cannot be made static, because they are defined in an interface. And at the time I would use them in Interpolator, I do not have an instance of Coordinate (or any Interpolatable) available.

Any suggestions?

(I understand why interface methods cannot be static; I just lack an idea how to elegantly solve a problem like this.)

Because of type erasure, you cannot do much with the generic type at runtime. You need to keep an instance or class object around:

class Interpolator <T extends Interpolatable> {
  private final T target;

  Interpolator (T target) {
    this.target = target;
    int dim = target.getDimension();
  }
  void doSomething (double d) {
    Iterator <? extends Interpolatable> it = target.getIterator(d);
    Interpolatable t = it.next();
    …
  }
}

Basically, you are never passing any instance of the interface to the class . You are just using calls to the type (class), vg T.getDimension();

Also you do not need generics at all for this. Plain old interfaces work the way that you want.

You can just do:

class Interpolator  {
  Interpolable interpolable = null;  
  Interpolator (Interpolable _interpolable) {
    this.interpolable = _interpolable;
  }

  void doSomething (double d) {
    Iterator<Interpolable> it = this.interpolable.getIterator(d);
    Interpolatable t = it.next();
    …
  }
}

I recommend that before getting into generics you work more used to interface, static/instance methods and other more basic stuff...

cant you say class Interpolator extends Coordinate

and then just call the method straight away...

I think you're simply overusing generics. This should work:

class Interpolator {
  Interpolatable myInterpolatable;

  Interpolator (Interpolatable i) {
    myInterpolatable = i;
    int dim = i.getDimension();
  }
  void doSomething (double d) {
    Iterator <Interpolatable> it = myInterpolatable.getIterator(d);
    Interpolatable t = it.next();
    …
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM