English 中文(简体)
Scala: 普通类构造器中的自型
原标题:Scala: Self types in Constructors for generic classes

这里的味道是 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 类,我需要通过通用参数而不是抽象类型来解决类型问题。所以我希望能够从一个类型参数中找到多种类型。所以在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
时 时

然后我用一种自我类型来创建我的网基类

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的型号成员, 尽管我可以在类体内很好地使用它们。 任何帮助都会感谢。 但是这也是将多种类型从一个类型参数中取出的最佳方法吗?

澄清:所有班级都在不同的文件中。这里没有内部班级。

最佳回答

在构建器中 T#HexT 如何?

_/code> 被称作 类型投影 ,用于指内型投影 。在术语中,我不够固,因此不会详细,但作为执行类型操作时使用 A#B 的准则(另见 https://stackoverf="https://stackoverf='https/8736164/west-a-type-lambdas- in-scala-and-what-a-a-em-are-em-em-e-e-eles-failitys ,而 则与 < a href="https://stackflow.com/ ques/576791/is-a-path-ind-a-subtytytytys" > a/path依赖型类型。

注意: 当 A 是包件或对象时, 那么 A.B 将按您预期的方式行事, 游戏将随特性或类而来。

虽然没有直接关联,但这可能证明是一个好读法: 单独是表达问题的广泛解决办法

问题回答

当然很难猜测, 但我认为你的班级应该这样看, “也许他们”(你必须改变很多,

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 拥有的同一外部类。

视使用大小写而定(自型要求您在 DescripType 的亚轨中混合使用),以下是更相容的:

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

您需要指定 < code> DescripType 的子类, 然后可以使用这些子类中定义的别名类型 。

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)




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...