Scala参数上类型边界和重写



我试图在我的系统中理解和合并上界类型与重写,但是没有一些丑陋的代码就无法实现它。我有以下两个特点:

trait MyId {
def getType: Int // For simplicity. This is Enum/Object in code.
def id: Any
}
trait MyTrait {
protected def supportedType: Int

def doSomething(id: MyId): Unit = {
if (id.getType == myType) 
doSomethingInternal(id)
}

protected def doSomethingInternal(id: _ <: MyId): Unit
}

和我想创建的子类型为:

class X(x: Long) extends MyId {
override def getType: Int = 1
override def id: Long = x
}
class Y(y: String) extends MyId {
override def getType: Int = 2
override def id: String = y
}
class A extends MyTrait {
override protected def supportedType: Int = 1
override protected def doSomethingInternal(id: X): Unit {...}
}
class B extends MyTrait {
override protected def supportedType: Int = 2
override protected def doSomethingInternal(id: Y): Unit {...}
}

然而,这不起作用。我一直在使用的解决方案是使用asInstanceOf[]:

class A extends MyTrait {
override protected def supportedType: Int = 1
override protected def doSomethingInternal(id: MyId): Unit {
val id2 = id.asInstanceOf[X]
}
}
class B extends MyTrait {
override protected def supportedType: Int = 2
override protected def doSomethingInternal(id: MyId): Unit {
val id2 = id.asInstanceOf[Y]
}
}

有办法摆脱asInstanceOf[]吗?

编辑

此外,我有以下处理器,需要根据给定的MyId.getType调用正确的MyTrait子类:

def process(ids: Seq[MyId], processors: Map[Int, MyTrait]): Unit = {
ids.foreach{ id =>
processors.get(id.getType).doSomething(id)
}
}

编辑2:

为了简单起见,这里的
  • getTypeInt。在我的代码中,这实际上是一个枚举/对象。
  • getSomething重命名为doSomething以更清晰。

从问题中不清楚是否有getSomethinggetSomethingInternal之间的间接特定需要,而不是getType一致性检查,但由于看起来目标只是为了防止用错误的id类型调用getSomething,在我看来,用预期id的类型参数定义MyTrait会更简单:

trait MyTrait[T] {
def getSomething(id: T): Unit
}
class A extends MyTrait[Long] {
def getSomething(id: Long): Unit = { println(s"long id: $id") }
}
class B extends MyTrait[String] {
def getSomething(id: String): Unit = { println(s"string id: $id") }
}

事情是这样的:

val a = A()
val b = B()
a.getSomething(123)
// prints "long id: 123"
b.getSomething("abc")
// prints "string id: abc"
a.getSomething("bad") // <--- doesn't compile
b.getSomething(123) // <--- doesn't compile

我不完全清楚你到底想做什么,但是,也许,这样的东西会起作用。关键是使用Type作为类型,而不是试图将其编码为Int然后转换为类型。

trait MyId[Type] {
def id: Type
}
trait MyTrait[T] {
def getSomething(id: MyId[T]): Unit = 
getSomethingInternal(id.id)


protected def getSomethingInternal(id: T): Unit
}

再一次,这很大程度上是在黑暗中拍摄,因为我不知道为什么你的类型是数字或为什么你的gets返回单位…

好的,如果你的类型是"枚举",你想把你的MyId设置为一个密封的trait:

sealed trait MyId[T] {
def id: T 
}
case class X(id: Long) extends MyId[Long]
case class Y(id: String) extends MyId[String]

但是现在您想要统一地处理您的id。如果处理器列表是静态的,只需执行match:

def process(ids: Seq[MyId[_]]) = ids.map { 
case x: X => processX(х)
case y: Y => processY(y)
}

如果不是呢?嗯. .在这种情况下,我会从另一个更新开始回答你的问题,解释你为什么需要它,以及你如何生成这个动态列表。

相关内容

  • 没有找到相关文章

最新更新