Java, расширяющий параметризованный класс

#java #generics

Вопрос:

Мне трудно понять следующее. Представьте, что у меня есть универсальный класс Nodelt;Tgt; для представления узлов двоичного дерева с некоторыми методами в нем.

 public class Nodelt;Tgt; {  T info;  Nodelt;Tgt; left;  Nodelt;Tgt; right;   public Node(T info) {this.info=info;}  //and some methods  }  

Теперь я хотел бы добавить метод для Node типа s Integer , который суммировал бы все узлы, до которых можно добраться из текущего:

 public int sum(){  int sum = this.info;  if(this.left!=null) sum =left.sum();  if(this.right!=null) sum =right.sum();  return sum;  }    

Я не совсем уверен, как это сделать. Я подумал о создании класса, который расширяется Nodelt;Integergt; , и добавлении sum туда метода:

 public class NodeOfIntegers extends Nodelt;Integergt;{    public NodeOfIntegers (T info) {super();}   public int sum(){...}    }  

но так left как и right относятся к типу Nodelt;Integergt; а не NodeOfIntegers я не могу сделать left.sum() и right.sum() .

Есть ли способ сделать это без переопределения left и right ?

Большое спасибо.

Ответ №1:

Используйте такую reduce функцию, как Stream обеспечивает:

 public static class Nodelt;Tgt;{   public Node(T value, Nodelt;Tgt; a, Nodelt;Tgt; b){  this.value = value;  this.a = a;  this.b = b;  }   private final Nodelt;Tgt; a,b;  private final T value;   private T reduce(T start,BinaryOperatorlt;Tgt; operator){  T reduced = operator.apply(start,value);  if(a != null)reduced = a.reduce(reduced,operator);  if(b != null)reduced = b.reduce(reduced,operator);  return reduced;  }  }    public static void main(String[] args) {  Nodelt;Integergt; integerNode = new Nodelt;gt;(4,new Nodelt;gt;(4,null,null),new Nodelt;gt;(2,null,null));  System.out.println(integerNode.reduce(0, Integer::sum));  }  

Ответ №2:

Вы должны определить свой T как

 class Nodelt;T extends Numbergt; {  }  

затем вы можете записать функцию sum в виде

 int sum() {  int sum = this.info.intValue(); }  

Комментарии:

1. Но это помешало бы мне параметризовать Node некоторые типы (например Nodelt;Stringgt; ), верно?

2. Да, конечно, тогда вам нужно проверить в методе sum , является ли общий экземпляр числа или нет, а затем действовать соответственно (поскольку вы не можете суммировать строки), или вы можете проанализировать его с помощью Long.valueOf() что-то в этом роде.

Ответ №3:

Вместо использования NodeOfInteger класса я бы определил в классе узлов a

 public T combine(BinaryOperatorlt;Tgt; combiner) {  T res = this.info;  if (this.left != null) res = combine(res, this.left.combine(combiner);  if (this.right != null) res = combine(res, this.right.combine(combiner);  return res; }  

который может быть использован как node.combine(Integer::sum) , или как node.combine(String::concat)

(Обратите внимание, что это может быть определено вне класса узлов, если это необходимо)