CptPicard
September 6th, 2008, 06:43 AM
Tinny, I'm looking at you... ;)
Ok, so here I've got another of these cases where I feel like I'm just fighting a static type system without really understanding how I should go about this :( (not to mention that dynamic typing would solve the problem trivially) So I would love to hear design ideas.
Situation is as such: I have a hierarchy of Analyzers for particular games. There is an abstract superclass AnalyzerBase, an abstract subclass SparseAnalyzerBase and then a number of concrete analyzers, let's just generally call a subclass of SparseAnalyzerBase a GameAnalyzer.
A common feature of all analyzers is that they manipulate a large array of Records, that have the following (simplified) interface:
public interface IAnalyzerRecord<T extends Comparable<? super T>> {
public ArrayList<T> getRow();
}
The array of "Comparables" is the key here as it is being used to implement lexical ordering of records. Implementations of IAnalyzerRecord are typically inner classes of various Analyzer classes.
AnalyzerBase and SparseAnalyzerBase are currently as follows
public abstract class AnalyzerBase<T extends IAnalyzerRecord<?>> implements Serializable {
...
public abstract class SparseAnalyzerBase<T extends IAnalyzerRecord<K extends Comparable<? super K>>>
extends AnalyzerBase<T> {
Now, these definitions are, of course, wrong, but should perhaps give an idea of what I am trying here. :(
I can make at least the compiler like the definitions of classes if I do SparseAnalyzerBase like so:
public abstract class SparseAnalyzerBase<T extends IAnalyzerRecord<?>>
extends AnalyzerBase<T> {
But the problem is that in SparseAnalyzerBase, I really want to "know" that IAnalyzerRecord really does return to me an ArrayList of Comparables, because this comparison info is to be used in searching records in methods that would be nicely shareable among subclasses.
In particular, if in SparseAnalyzerBase I attempt to do
private void foo(T x) {
x.getRow().get(0).compareTo(x.getRow().get(1));
}
// barfs with
The method compareTo(? super T) in the type Comparable<? super T> is not applicable for the arguments (capture#2-of ?)
I can make the compiler shut up with
public abstract class SparseAnalyzerBase<T extends IAnalyzerRecord<? extends Comparable>>
extends AnalyzerBase<T> {
but this of course results in warnings,
Comparable is a raw type. References to generic type Comparable<T> should be parameterized
Which is probably ok as I know I won't be giving it weird stuff at runtime, but I still would love to hear if I'm doing it wrong and there are better ideas, I am quite uncomfortable with this...
I willingly admit that I suck at generics and always just feel like I'm doing some voodoo to make the compiler like me....
EDIT: Hmmph... I found a way to do it by explicitly declaring the "row item" type, I still don't quite like it though...
public abstract class SparseAnalyzerBase<I extends Comparable<? super I>, T extends IAnalyzerRecord<I>>
extends AnalyzerBase<I, T> {
Ok, so here I've got another of these cases where I feel like I'm just fighting a static type system without really understanding how I should go about this :( (not to mention that dynamic typing would solve the problem trivially) So I would love to hear design ideas.
Situation is as such: I have a hierarchy of Analyzers for particular games. There is an abstract superclass AnalyzerBase, an abstract subclass SparseAnalyzerBase and then a number of concrete analyzers, let's just generally call a subclass of SparseAnalyzerBase a GameAnalyzer.
A common feature of all analyzers is that they manipulate a large array of Records, that have the following (simplified) interface:
public interface IAnalyzerRecord<T extends Comparable<? super T>> {
public ArrayList<T> getRow();
}
The array of "Comparables" is the key here as it is being used to implement lexical ordering of records. Implementations of IAnalyzerRecord are typically inner classes of various Analyzer classes.
AnalyzerBase and SparseAnalyzerBase are currently as follows
public abstract class AnalyzerBase<T extends IAnalyzerRecord<?>> implements Serializable {
...
public abstract class SparseAnalyzerBase<T extends IAnalyzerRecord<K extends Comparable<? super K>>>
extends AnalyzerBase<T> {
Now, these definitions are, of course, wrong, but should perhaps give an idea of what I am trying here. :(
I can make at least the compiler like the definitions of classes if I do SparseAnalyzerBase like so:
public abstract class SparseAnalyzerBase<T extends IAnalyzerRecord<?>>
extends AnalyzerBase<T> {
But the problem is that in SparseAnalyzerBase, I really want to "know" that IAnalyzerRecord really does return to me an ArrayList of Comparables, because this comparison info is to be used in searching records in methods that would be nicely shareable among subclasses.
In particular, if in SparseAnalyzerBase I attempt to do
private void foo(T x) {
x.getRow().get(0).compareTo(x.getRow().get(1));
}
// barfs with
The method compareTo(? super T) in the type Comparable<? super T> is not applicable for the arguments (capture#2-of ?)
I can make the compiler shut up with
public abstract class SparseAnalyzerBase<T extends IAnalyzerRecord<? extends Comparable>>
extends AnalyzerBase<T> {
but this of course results in warnings,
Comparable is a raw type. References to generic type Comparable<T> should be parameterized
Which is probably ok as I know I won't be giving it weird stuff at runtime, but I still would love to hear if I'm doing it wrong and there are better ideas, I am quite uncomfortable with this...
I willingly admit that I suck at generics and always just feel like I'm doing some voodoo to make the compiler like me....
EDIT: Hmmph... I found a way to do it by explicitly declaring the "row item" type, I still don't quite like it though...
public abstract class SparseAnalyzerBase<I extends Comparable<? super I>, T extends IAnalyzerRecord<I>>
extends AnalyzerBase<I, T> {