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 クラスの場合、抽象型ではなくジェネリックを介して型を解決する必要があります。そのため、1 つの型パラメーターから複数の型を取得できるようにしたいと考えています。そこで、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 の型メンバーを使用できないようですが、クラス本体内では問題なく使用できます。どんな助けでも感謝します。しかし、これは 1 つの型パラメーターから複数の型を取得するための最良の方法ですか?

明確化: すべてのクラスは別々のファイルにあります。ここには内部クラスはありません。

4

2 に答える 2

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任意を取ります。HexTmyHex

ユースケースに応じて (自己型では のサブトレイトを混在させる必要があります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 に答える
2

T#HexTコンストラクタではどうですか?

#型射影と呼ばれ、内部型を参照するために使用されます。私は用語に固執していないので、詳細には触れませんが、A#B型レベルの操作を実行するときに使用するガイドラインとして ( type lambdasも参照してください)、 whileはpath-dependent typesA.Bに関連しています。

注:Aがパッケージまたはオブジェクトであり、A.B期待どおりに動作する場合#、トレイトまたはクラスで楽しみが生まれます。

直接関係はありませんが、これは良い読み物になるかもしれません:式の問題に対する独立して拡張可能なソリューション

于 2012-05-22T15:15:22.833 に答える