为编译时安全性引入类型约束

时间:2015-12-08 19:12:31

标签: scala

如果我们有一个带有一些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编译时类型安全/已检查。解决这个问题的正确方法是什么?

2 个答案:

答案 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))
  }
}