Java, дженерики и статические методы - PullRequest
2 голосов
/ 10 августа 2011

Я хотел бы иметь общий класс Interpolator, который может интерполировать между экземплярами классов, реализующих Интерполируемый интерфейс:

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();
    …
  }
}

Конечно, компилятор жалуется на T.getDimension() и T.getIterator(d):

Невозможно сделать статическую ссылку на нестатический метод getDimension () / getIterator (double) из типа Interpolatable.

Однако два метода нельзя сделать статическими, поскольку они определены в интерфейсе. И в то время, когда я использовал бы их в Интерполяторе, у меня нет доступного экземпляра Координаты (или любого Интерполируемого).

Есть предложения?

(Я понимаю, почему методы интерфейса не могут быть статичными; мне просто не хватает идеи, как элегантно решить такую ​​проблему).

Ответы [ 4 ]

4 голосов
/ 10 августа 2011

Из-за стирания типа вы не можете многое сделать с универсальным типом во время выполнения.Вам необходимо хранить экземпляр или объект класса:

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();
    …
  }
}
4 голосов
/ 10 августа 2011

По сути, вы никогда не передаете какой-либо экземпляр интерфейса классу .Вы просто используете вызовы типа (класса), vg T.getDimension ();

Также для этого вам не нужны универсальные шаблоны.Обычные старые интерфейсы работают так, как вы хотите.

Вы можете просто сделать:

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();
    …
  }
}

Я рекомендую перед тем, как приступить к обобщению, вы должны больше использовать интерфейс, статические методы / методы экземпляра и другиеболее простые вещи ...

0 голосов
/ 10 августа 2011

Я думаю, вы просто злоупотребляете дженериками.Это должно работать:

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();
    …
  }
}
0 голосов
/ 10 августа 2011

Вы не можете сказать class Interpolator extends Coordinate

, а затем просто вызвать метод сразу ...

...