I have the following two interfaces:
public interface ParsedFile<K, V extends FileEntry>{...}
And
public interface MetricsProduces<K, V extends FileEntry>{
Metrics generateMetrics(ParsedFile<K, V> parsedFile);
}
I have the following generic code the should be able to handle any FileEntry types:
Option<FileDefinition> option = fileContainer.matchFile(file);
if (option.isSome){
FileDefinition fileDef = option.some();
ParsedFileFactory<?> factory = filterDefinition.getFactory();
ParsedFile<?, ?> parsedFile = factory.parseFile(file);
MetricsProducer<?, ?> metricsProducer = fileDefinition.getMetricsProducer();
Metrics metrics = metricsProducer.generateMetrics(parsedFile);
}
This block of code is designed to be able to parse any type of file given the appropriate FileDefinition. However I am getting the following compile-time error:
The method generateMetrics(ParsedFile<capture#5-of ?, capture#6-of ? extends FileEntry>)
in the type MetricsProducer<capture#5-of ?, cature#6-of ? extends FileEntry>
is not applicable for the arguments
(ParsedFile<capture#7 of ?, capture#8-of ? extends FileEntry>)
Is there a way to let the compiler know that the “?” type of ParsedFile is the same as the “?” type of MetricsProducer? Is there another option for doing this?
Edit:
I have fixed (as noted this causes a cast warning) the code as follows but was wondering if there is a better option:
public interface MetricsProduces<K, V extends FileEntry>{
Metrics generateMetrics(ParsedFile<?, ? extends FileEntry> parsedFile);
}
public class TasksMetricsProduces<String, TaskFileEntry> implements MetricsProduces<...>{
public Metrics generateMetrics(ParsedFile<?, ? extends FileEntry> parsedFile){
ParsedFile<String, TaskFileEntry> parsedFile2 = (ParsedFile<String, TaskFileEntry>)parsedFile;
}
}
Edit 2: per comments / suggestions
So I found that if I lock down the types earlier I can do the following:
public interface FileDefinition<K, V extends FileEntry, T extends ParsedFile<K, V>>{...
public void myMethod(){
for (FileDefinition<?, ?, ?> def : defs){
process(def);
}
}
private <K, V extends FileEntry, T extends ParsedFile<K, V>> process(FileDefinition<K, V, T> def){
Factory<T> factory = def.getFactory();
MetricsProducer<K, V> producer = def.getMetricsProducer();
ParsedFile<K, V> parsedFile = factory.parseFile();
Metrics metrics = producer.generateMetrics(parsedFile);
}
Thanks for the suggestions.
Found that it worked if I locked down the generic types earlier to show the compiler that the types for the objects are the same.