In this period I am working on a project which requires some kind of abstraction, but I don't know how to solve some problems related to java generics and type inference.
This is a simplified architecture of the source code:
public abstract class BaseDataset
{
// Some data
// Some methods
}
public class DerivedDataset1 extends BaseDataset
{
// Some data
// Implementations of some BaseDataset methods
// Some additional methods
}
public class DerivedDataset2 extends BaseDataset
{
// Some data
// Implementations of some BaseDataset methods
// Some additional methods
}
public interface BaseMeasure<T extends BaseDataset>
{
public float evaluate(T dataset);
}
public class DerivedMeasure1 implements BaseMeasure<DerivedDataset1>
{
@Override
public float evaluate(DerivedDataset1 dataset)
{
// evaluate some measure using DerivedDataset1 methods
return the evaluated measure;
}
}
public class DerivedMeasure2 implements BaseMeasure<DerivedDataset2>
{
@Override
public float evaluate(DerivedDataset1 dataset)
{
// evaluate some measure using DerivedDataset2 methods
return the evaluated measure;
}
}
public class SocialNetworkBuilder
{
public <T extends BaseDataset> void build(T dataset, BaseMeasure<T> measure)
{
float weight = measure.evaluate(dataset);
// ...
}
}
My problem is that if, in my main class, I write something like this:
public class Application
{
public static void main(String [] args)
{
BaseDataset dataset = new DerivedDataset1();
BaseMeasure<? extends BaseDataset> measure = new DerivedMeasure1();
SocialNetworkBuilder socialNetworkBuilder = new SocialNetworkBuilder();
socialNetworkBuilder.build(dataset, measure);
}
}
Eclipse gives me the error: "The method build(T, BaseMeasure) in the type SocialNetworkBuilder is not applicable for the arguments (BaseDataset, BaseMeasure)"
I think the problem is that the "build" method has to be sure that dataset and measure are of the same type T.
If I do something like this:
public class Application
{
public static void main(String [] args)
{
BaseDataset dataset = new DerivedDataset1();
BaseMeasure<? extends BaseDataset> measure = new DerivedMeasure1();
SocialNetworkBuilder socialNetworkBuilder = new SocialNetworkBuilder();
socialNetworkBuilder.build((DerivedDataset1) dataset, (DerivedMeasure1) measure);
}
}
it works, but I can't solve my problem in this way because I don't know the derived type of my "dataset" and "measure" instances at compile-time; "dataset" and "measure" should be instanced depending on some parameters given at runtime.
I need to instance my "measure" and "dataset" variables at runtime and still be able to call the "build" method on them.
Do you have some ideas to solve this problem?
Thank you.
Your application will compile when you change it as follows:
public class Application
{
public static void main(String [] args)
{
DerivedDataset1 dataset = new DerivedDataset1();
BaseMeasure<DerivedDataset1> measure = new DerivedMeasure1();
SocialNetworkBuilder socialNetworkBuilder = new SocialNetworkBuilder();
socialNetworkBuilder.build(dataset, measure);
}
}