2013-11-23 117 views
2

在此期間,我正在研究一個需要某種抽象的項目,但我不知道如何解決與Java泛型和類型推理相關的一些問題。在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類型中的方法構建(T,BaseMeasure)不適用於參數(BaseDataset,BaseMeasure)」

我認爲問題在於「構建」方法h爲確保數據集和措施是同一類型的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); 
    } 
} 

它的工作原理,但我不能這樣解決我的問題,因爲我不在編譯時不知道我的「數據集」和「度量」實例的派生類型; 「數據集」和「度量」應根據運行時給出的一些參數進行實例化。

我需要在運行時實例化我的「測量」和「數據集」變量,並仍然可以調用它們的「構建」方法。

你有解決這個問題的一些想法嗎?

謝謝。

回答

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

謝謝你的回答。我知道我的應用程序將編譯,如果我以這種方式更改它,但我需要實例數據集和測量基類與一些特定的類取決於用戶參數... – JohnQ

+0

泛型在編譯時進行評估。如果使用基本類型而不是實際類型,編譯器無法知道兩者是「兼容的」。所以我認爲你應該在沒有泛型的情況下嘗試它。想想使用泛型的好處是什麼! – isnot2bad

+0

我能看到的泛型的唯一好處是具體派生的度量可以確保他們得到正確的派生數據集。這對他們很重要嗎? – isnot2bad

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