【问题标题】:class as argument, scala.类作为参数,scala。
【发布时间】:2013-10-09 20:04:17
【问题描述】:

作为我的代码的简化版本:

abstract class GenX
case class X1 extends GenX
case class X2 extends GenX
...

class A {
 val ab : LinkedList[X1] = LinkedList()
 val ac : LinkedList[X2] = LinkedList()
 ...
 def addX[T <: GenX]( x : GenX, clazz : T) =
   getList(clazz) append LinkedList(x) // HERE complains

 def getList(T <: GenX) (clazz : T) : LinkedList[_<: GenX] = clazz match {
  case X1 => ab
  case X2 => ac
  ...
  }
}

我的意图是,当需要将 GenX 添加到 A 时,它可以将其类作为参数传递给通用添加,例如

case class X1 extends GenX{
 def addToA(a : A) = a.addX(this, this getClass)
}

现在的问题是编译器抱怨 x 是 GenX 类型而不是 _$1 <: genx>

我不明白。

【问题讨论】:

  • 个人笔记,我不认为def addToA(a : A) = a.ab append LinkedList(this) 是一个很好的解决方案,对于封装问题

标签: scala metaprogramming


【解决方案1】:

首先,关于追加,我建议使用ListBuffer 而不是LinkedList,它有一个更友好的追加API。

接下来,您对 clazz 参数的声明将其声明为 T 类型(GenX 的子类型),而不是 Class[T]。无论如何,你最好只匹配x

最后,x 被声明为GenX 类型,并且编译器可以判断出可能是GenXclazz 或所选列表的子类类型不同的子类,因此是实际编译你会收到错误。

这是 A 的一个版本,应该可以实现您的目标:

import scala.collection.mutable.ListBuffer

class A {
  val ab : ListBuffer[X1] = ListBuffer()
  val ac : ListBuffer[X2] = ListBuffer()
  // ...

  def addX(x: GenX) = x match {
    case x1: X1 => ab += x1
    case x2: X2 => ac += x2
    // ...
  }         
}

【讨论】:

  • 谢谢!这解决了我的问题。我非常专注于这个问题,我没有意识到我可以混合使用 addX 和 getList。只是想知道,您的版本的 getList 返回类型是什么,因为: ListBuffer[GenX] 是一个编译错误,但我认为它实际上是一个 ListBuffer[GenX]。
  • 我认为乍一看很奇怪的东西。当我在 REPL 中尝试上述操作时,a.addX(x) 给出了(大约)ListBuffer[_ &gt;: X1 with X2 &lt;: GenX] 的结果。我认为这应该被解释为好像在 X1 with X2 部分周围有括号(这将扩展到 ... with X3 with ... 以了解更多涉及的 GenX 子类型)。
  • 哦,那真是令人讨厌的东西。我想知道返回类型,因为现在我需要一个removeX(x : GenX),除了+= xn 之外,它基本上是相同的代码。但如果它是有线的,我会用复制和粘贴来改变每个案例的结尾。再次感谢
猜你喜欢
  • 2015-03-22
  • 1970-01-01
  • 2016-12-05
  • 1970-01-01
  • 2013-05-24
  • 2022-01-27
  • 2018-11-21
  • 1970-01-01
  • 2015-06-30
相关资源
最近更新 更多