I am trying to understand and incorporate upper bound types with overriding in my system, but have not been able to achieve it without some ugly code. I have the following 2 traits:
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
}
and I want to create subtypes as:
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 {...}
}
However, this does not work. The workaround I have been using is to use 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]
}
}
Is there a way I can get rid of the asInstanceOf[]
?
EDIT
Further more, I have the following processor which requires calling the correct MyTrait
subclass based on the given MyId.getType
:
def process(ids: Seq[MyId], processors: Map[Int, MyTrait]): Unit = {
ids.foreach{ id =>
processors.get(id.getType).doSomething(id)
}
}
Edit 2:
getType
isInt
for simplicity here. This is actually an enum/object in my code.- Renamed
getSomething
todoSomething
for more clarity.