0

下面是我移植到 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 类构造函数中使用 DescriptTypes 的类型成员,尽管我可以在类主体中很好地使用它们。任何帮助表示赞赏。但这也是从一个类型参数中获取多种类型的最佳方法吗?

澄清:所有类都在单独的文件中。这里没有内部类。

4

2 回答 2

2

T#HexT在构造函数中怎么样?

#称为类型投影,用于指代内部类型。我不熟悉术语,因此不会详细介绍,但作为A#B执行类型级操作时使用的指南(另请参见type lambdas),而A.Bpath-dependent types 相关

注意:当A是一个包或对象时,它的A.B行为与您期望的一样,#有趣的是特性或类。

虽然不直接相关,但这可能证明是一个很好的阅读:表达问题的独立可扩展解决方案

于 2012-05-22T15:15:22.833 回答
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
  }
}

在您的示例mymethodHexT,我认为您希望将其限制为具有相同的外部类myHex

根据用例(self-type 要求您混入 的子特征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)
于 2012-05-22T15:23:54.480 回答