Re: Multiple template classes with different parameter lists
David R Tribble wrote:
And obviously you can go the other way, too:
class Tuple2<T1, T2> { ... }
class Tuple3<T1, T2, T3> extends Tuple2<T1, T2> { ... }
class Tuple4<T1, T2, T3, T4> extends Tuple3<T1, T2, T3> { ... }
etc.
Alternatively, you may use just two classes:
public class Tuple<T, N extends Tuple<?, ?>> {
public static final class Empty extends Tuple<Empty, Empty> {
public static final Empty INSTANCE = new Empty();
private Empty() {
super(null);
}
@Override
public int length() {
return 0;
}
public void setArg(Empty arg) {
throw new UnsupportedOperationException();
}
}
private T arg;
private N next;
private Tuple(T arg, N next) {
if (next == null) throw new NullPointerException();
this.arg = arg;
this.next = next;
}
private Tuple(T arg) {
this.arg = arg;
this.next = null;
}
public T getArg() {
return arg;
}
public int length() {
return next != null ? next.length() + 1 : 1;
}
public void setArg(T arg) {
this.arg = arg;
}
public N next() {
return next;
}
public static <T, N extends Tuple<?, ?>> Tuple<T, N>
get(T arg, N next) {
return new Tuple<T, N>(arg, next);
}
public static <T> Tuple<T, Empty> get(T arg) {
return new Tuple<T, Tuple.Empty>(arg);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(length()).append("-tuple: ");
sb.append("[");
if (this != Empty.INSTANCE) {
sb.append(arg);
for(Tuple<?, ?> next = this.next; next != null; next =
next.next) {
sb.append(", ");
sb.append(next.arg);
}
}
sb.append("]");
return sb.toString();
}
}
Sample usage:
Tuple.Empty t0
= Tuple.Empty.INSTANCE;
Tuple<Integer, Tuple.Empty> t1
= Tuple.get(1);
Tuple<Integer, Tuple<Integer, Tuple.Empty>> t2
= Tuple.get(1, Tuple.get(2));
Tuple<Integer, Tuple<String, Tuple<Object, Tuple.Empty>>> t3
= Tuple.get(1, Tuple.get("two", Tuple.get(null)));
System.out.println(t0);
System.out.println(t1);
System.out.println("a0=" + t1.getArg());
System.out.println(t2);
System.out.println("a0=" + t2.getArg());
System.out.println("a1=" + t2.next().getArg());
System.out.println(t3);
System.out.println("a0=" + t3.getArg());
System.out.println("a1=" + t3.next().getArg());
System.out.println("a2=" + t3.next().next().getArg());
t3.next().next().setArg(3);
System.out.println(t3);
For convenience, you may also add a couple of extra methods to the Tuple
class, e.g.:
public static <T> void setArg0(Tuple<T, ?> tuple, T value) {
tuple.setArg(value);
}
public static <T> T getArg0(Tuple<T, ?> tuple) {
return tuple.getArg();
}
public static <T> void setArg1(Tuple<?, Tuple<T, ?>> tuple, T value) {
tuple.next().setArg(value);
}
public static <T> T getArg1(Tuple<?, Tuple<T, ?>> tuple) {
return tuple.next().getArg();
}
public static <T> void setArg2(Tuple<?, Tuple<?, Tuple<T, ?>>>
tuple, T value) {
tuple.next().next().setArg(value);
}
public static <T> T getArg2(Tuple<?, Tuple<?, Tuple<T, ?>>> tuple) {
return tuple.next().next().getArg();
}
// and so on...
piotr