如果我们有一个带有一些ADT的类型如下
trait MyRule {
type T
class ResourceIdType[A](val value: A)
case class StringResourceIdType(override val value: String) extends ResourceIdType(value)
case class ListResourceIdType(override val value: List[Int]) extends ResourceIdType(value)
def resourceType(rtm: T) : Any
private foo(rtm: T ) = {
resourceType(rtm) match{
case StringResourceIdType(s: String) =>
case ListResourceIdType(l:List[Int]) =>
...
}
type class impls覆盖def resourceType
,如下所示
object FirstClient{
implicit val clientRule = new MyRule{
type T = SomeType
def resourceType(rtm: T) = StringResourceIdType(rtm.name) //assume SomeType has a name property of type String
}
}
object SecondClient{
implicit val clientRule2 = New MyRule{
type T = SomeType2
def resourceType(rtm: T) = ListResourceIdType(rtm.ids) //assume SomeType2 has a ids property of type List[Int]
}
}
要删除def resourceType(rtm: T) : Any
并使用有效类型Any
替换,以使T <: ResourceIdType
编译时类型安全/已检查。解决这个问题的正确方法是什么?
答案 0 :(得分:1)
您可以在MyRule trait
中添加类型参数,并在每个类型类中对其进行优化:
trait MyRule {
type T
class ResourceIdType[A](val value: A)
case class StringResourceIdType(override val value: String) extends ResourceIdType(value)
case class ListResourceIdType(override val value: List[Int]) extends ResourceIdType(value)
type F <: ResourceIdType[_]
def resourceType(rtm: T) : F
private def foo(rtm: T): Unit = {
resourceType(rtm) match {
case StringResourceIdType(s: String) =>
case ListResourceIdType(l:List[Int]) =>
}
}
}
object FirstClient{
implicit val clientRule = new MyRule{
case class SomeType(name: String)
type T = SomeType
type F = StringResourceIdType
def resourceType(rtm: T) = StringResourceIdType(rtm.name) //assume SomeType has a name property of type String
}
}
object SecondClient{
implicit val clientRule2 = new MyRule{
case class SomeType2(ids: List[Int])
type T = SomeType2
type F = ListResourceIdType
def resourceType(rtm: T) = ListResourceIdType(rtm.ids) //assume SomeType2 has a ids property of type List[Int]
}
}
答案 1 :(得分:0)
以下编译。如果它能解决您的问题,请告诉我。
package net
trait SomeType {
def name: String
}
trait SomeType2 {
def ids: List[Int]
}
// Introduce an Algebraic Data Type
class ResourceValue
case class StringValue(x: String) extends ResourceValue
case class ListIntsValue(x: List[Int]) extends ResourceValue
trait MyRule {
type T
sealed trait ResourceIdType {
val value: ResourceValue
}
case class StringResourceIdType(override val value: StringValue) extends ResourceIdType
case class ListResourceIdType(override val value: ListIntsValue) extends ResourceIdType
def resourceType(rtm: T): ResourceIdType
private def foo(rtm: T): ResourceValue = {
resourceType(rtm) match {
case StringResourceIdType(s @ StringValue(_)) => s
case ListResourceIdType(l @ ListIntsValue(_)) => l
}
}
}
object FirstClient{
implicit val clientRule = new MyRule {
type T = SomeType
override def resourceType(rtm: T): ResourceIdType =
StringResourceIdType(StringValue(rtm.name))
}
}
object SecondClient{
implicit val clientRule2 = new MyRule {
type T = SomeType2
override def resourceType(rtm: T): ResourceIdType =
ListResourceIdType(ListIntsValue(rtm.ids))
}
}