2

在此期间,我正在从事一个需要某种抽象的项目,但我不知道如何解决与 java 泛型和类型推断相关的一些问题。

这是源代码的简化架构:

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);

        // ...
    }
}

我的问题是,如果在我的主课中,我写了这样的东西:

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 给了我错误:“SocialNetworkBuilder 类型中的方法 build(T, BaseMeasure) 不适用于参数 (BaseDataset, BaseMeasure)”

我认为问题在于“构建”方法必须确保数据集和度量属于同一类型 T。

如果我做这样的事情:

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);
    }
}

它有效,但我无法以这种方式解决我的问题,因为我在编译时不知道我的“数据集”和“测量”实例的派生类型;应该根据运行时给出的一些参数来实例化“数据集”和“测量”。

我需要在运行时实例化我的“测量”和“数据集”变量,并且仍然能够在它们上调用“构建”方法。

你有一些想法来解决这个问题吗?

谢谢你。

4

2 回答 2

2

当您按以下方式更改应用程序时,您的应用程序将编译:

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);
    }
}
于 2013-11-23T14:09:15.767 回答
1

我认为您的代码没有问题。原则上应该是正确的,但是类型推断功能不足以处理BaseMeasure<DerivedDataset1>和之间的传递类型依赖DerivedDataset1 extends BaseDataset

例如,在 Scala 中,您的原始代码可以正常工作。

object DataSet  extends App {

    abstract class BaseDataset  

    class DerivedDataset1 extends BaseDataset   

    class DerivedDataset2 extends BaseDataset   

    trait BaseMeasure[T <: BaseDataset] {
        def evaluate(dataset:T):Float
    }

    class DerivedMeasure1 extends BaseMeasure[DerivedDataset1] {
        override def evaluate(dataset: DerivedDataset1) = 0
    }

    class DerivedMeasure2 extends BaseMeasure[DerivedDataset2]  {
        override def evaluate(dataset: DerivedDataset2) = 1
    }

    class SocialNetworkBuilder {
        def  build[T <: BaseDataset](dataset: T, measure:BaseMeasure[T] ) : Unit = {
            val weight = measure.evaluate(dataset);
            println(weight)
        }
    }

    val dataset1 = new DerivedDataset1()
    val measure1 = new DerivedMeasure1()
    val dataset2 = new DerivedDataset2()
    val measure2 = new DerivedMeasure2()
    val socialNetworkBuilder = new SocialNetworkBuilder()
    socialNetworkBuilder.build(dataset1, measure1)
    socialNetworkBuilder.build(dataset2, measure2)
}
于 2013-11-23T16:47:52.970 回答