#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)
(Обратите внимание, что это может быть определено вне класса узлов, если это необходимо)