以下是我正在移植到Scala中的C#代码的味道。无需担心细节。
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; } }
}
正如Martin Odersky所指出的那样,泛型问题是类型参数引用的数量和它们的约束参考往往会爆炸。但是对于GridBase类,我需要通过泛型而不是抽象类型来解析类型。所以我希望能够从一个类型参数中获取多个类型。所以在Scala中我为我的类型创建了一个特征:
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
}
然后我使用自我类型
创建我的Gridbase类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类构造函数中使用DescripTypes的类型成员,尽管我可以在类体内使用它们。任何帮助赞赏。但这也是从一个类型参数中获取多个类型的最佳方法吗?
澄清:所有类都在单独的文件中。这里没有内部课程。
答案 0 :(得分:2)
构造函数中的T#HexT
怎么样?
#
被称为type projection,用于指代内部类型。我在术语上不够扎实,所以不会详细说明,但作为指导,您在执行类型级操作时使用A#B
(另请参阅type lambdas),而A.B
则相关到path-dependent types。
注意:当A
是一个包或对象时,A.B
的行为就像您期望的那样,#
乐趣与特征或类一起发挥作用。
虽然没有直接关系,但这可能是一个很好的解读:Independently Extensible Solutions to the Expression Problem
答案 1 :(得分: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
的子特征),以下更合适:
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)