2012-05-22 211 views
0

下面介紹了我正在移植到Scala中的C#代碼。無需擔心細節。Scala:泛型類的構造函數中的自我類型

public class GridBase<HexT, SideT, UnitT, SegT> : IGridBase 
    where HexT : Hex 
    where SideT : Side 
    where UnitT : Unit 
    where SegT : ISeg 
{ 
    public GridBase(Geometry<HexT, SideT, UnitT, SegT> geom, IGridBase orig) 
    { 
    this.geom = geom; 
    } 
} 

public class Scen: Descrip<HexC, SideC, UnitC>, IListsGeom<HexC, SideC, UnitC> 
{ 
    public Geometry<HexC, SideC, UnitC, ISegC> geomC; 
    public override IGeom iGeom { get { return geomC; } } 
    public HexCList hexCs { get; private set; } 
    public override HexList<HexC> hexs { get { return hexCs; } } 
    public SideCList sideCs { get; private set; } 
    public override SideList<SideC> sides { get { return sideCs; } } 
    public UnitCList unitCs { get; private set; } 
    public override KeyList<UnitC> units { get { return unitCs; } } 
}  

正如馬丁·奧德斯基指出了問題泛型是類型參數的引用文件,其約束引用的數量往往爆炸。但是對於GridBase類,我需要通過泛型來解析類型,而不是抽象類型。所以我想能夠從一個類型參數中獲取多種類型。因此,在斯卡拉我創建的特質對我的類型:

abstract class Hex(val num1: Int){} //These are declared in their own files 
abstract class Side {val sideString = "This is a side"} 

trait DescripTypes //separate file 
{ 
    type HexT <: Hex 
    type SideT <: Side 
} 

class ScenTypes extends DescripTypes //separate file 
{ //This is an ex of an implemntation of the above in a different package 
    type HexT = HexC 
    type SideT = SideC 
} 

然後,我使用的是自型

class GridBase[T <: DescripTypes](val myHex: HexT) extends DescripTypes 
{//Compiler doesn't recognise the HexT type in the constructor 
    other: DescripTypes => 
    type other = T 

    var testvar = 5 //The rest does nothing at useful at the moment 
    var testvar2 = "" //just for testing 
    def mymethod(var1: HexT) //Compiler recognises HexT 
    { 
    testvar += var1.num1 //This compiles fine 
    } 
    def method2(var1: SideT) //Compiler recognises SideT 
    { 
    testvar2 = var1.sideString //This compiles fine 
    } 

}

出於某種原因,我似乎無法使用創建我Gridbase類雖然我可以在課程正文中使用它們,但它仍然是GridBase類構造函數中DescripTypes的類型成員。任何幫助讚賞。但是,這是從一個類型參數中獲取多種類型的最佳方式嗎?

說明:所有類都在單獨的文件中。這裏沒有內部課程。

回答

2

T#HexT如何在構造函數?

#被稱爲type projection,用於指代內部類型。我在術語上並不固定,所以不會詳細說明,但作爲執行類型級操作時使用A#B的指導(另請參閱type lambdas),而A.Bpath-dependent types有關。

注意:當A是一個包或對象時,A.B的行爲與您所期望的相同,#樂趣會隨特質或類別發揮作用。

雖然沒有直接的關係,這可能被證明是一個良好的閱讀:Independently Extensible Solutions to the Expression Problem

+0

好的,可能是直接相關的。但我留下了深思,作爲一個excercise :) – ron

+0

好偉大的似乎工作,但我不知道爲什麼。我能找到的#運算符的唯一文檔是針對內部外部類的。 –

+0

@RichOliver我更新了帖子。 – ron

2

這當然很難猜測,但我認爲你們班應該也許(你不得不改變相當多,使它實際上工作)這個樣子

class GridBase[T <: DescripTypes](val myHex: T#HexT) { this: T => 
    var testvar = 5 
    var testvar2 = "" 
    def mymethod(var1: HexT) { 
    testvar += var1.num1 
    } 
    def method2(var1: SideT) { 
    testvar2 = var1.sideString 
    } 
} 

在您的例子mymethod採取任何HexT而我想你想將其限制在相同外部類myHex了。

根據不同的使用情況,(自類型要求你混合式的DescripTypes子性狀),下面是更appropiate:

class GridBase[T <: DescripTypes](val myHex: T#HexT) { 
    var testvar = 5 
    var testvar2 = "" 
    def mymethod(var1: T#HexT) { 
    testvar += var1.num1 
    } 
    def method2(var1: T#SideT) { 
    testvar2 = var1.sideString 
    } 
} 

你必須指定子類DescripTypes,然後可以使用這些子類中定義的類型別名。

val scenType = new ScenTypes 
val scenTypeHex = new scenType.HexT 
val scenTypeSide = new scenType.SideT 
val gb_st = new GridBase[ScenTypes](scenTypeHex) 
gb_st.mymethod(scenTypeHex) 
gb_st.method2(scenTypeSide) 

// and the same for some other subclass of DescribTypes 
val scenType2 = new ScenTypes2 
val scenType2Hex = new scenType2.HexT 
val scenType2Side = new scenType2.SideT 
val gb_st2 = new GridBase[ScenTypes2](scenType2Hex) 
gb_st2.mymethod(scenType2Hex) 
gb_st2.method2(scenType2Side) 

// Does not compile: 
gb_st2.method2(scenTypeSide) 
+0

希望編輯已澄清。我不認爲這裏有任何內部課程。這些示例沒有用處,因爲它們不返回特定的類型。 –

+0

感謝「this:T =>」更整潔。 –

+0

@RichOliver DescripTypes#HexT是一個抽象的內部類型 – ron

相關問題