Scala 我应该创建特征来表示模型的枚举值吗?

Scala 我应该创建特征来表示模型的枚举值吗?,scala,slick,Scala,Slick,假设我有一个这样的模型: case class User( id: Int, name: String, userType: Int) 我是否应该这样做: sealed trait UserType case object Member() extends UserType case object Anonymous() extends UserType 我还应该为每个用户类型关联一个值 然后,我会将User case类更改为具有UserType属性,而不是int 我想接下来我会为sl

假设我有一个这样的模型:

case class User(
 id: Int,
 name: String,
 userType: Int)
我是否应该这样做:

sealed trait UserType
case object Member() extends UserType
case object Anonymous() extends UserType
我还应该为每个用户类型关联一个值

然后,我会将User case类更改为具有UserType属性,而不是int

我想接下来我会为slick创建一个隐式转换器,我相信它是一个从int到UserType的MappedColumnType

更新
这是用于使用slick db访问的。

我会用另一种方法。根据扩展
user
的场景,我会为用户设置一个类型:

sealed trait User
case class NormalUser(name: String, id: Int) extends User
case class SuperUser(name: String, id: Int, superPowers: Map[String, String]) extends User
然后在需要时对实际的
用户
类型进行模式匹配。

我选择enum:

object UserType extends Enumeration {
  type UserType = Value

  val Member = Value("Member")
  val Anonymous = Value("Anonymous")
}
还有你说的转换器:

implicit val userTypeColumnType = MappedColumnType.base[UserType, String](
  userType => userType.toString,
  UserType.withName
)
然后可以在
User
案例类中使用
userType:userType
。 在表定义中,可以有
def userType=column[userType](“用户类型”)

更新 选择enum而不是trait的原因之一是,如果不显式放置超类型,slick无法找到此隐式转换器。 例如

屈服

type mismatch;
[error]  found   : Member.type
[error]  required: slick.lifted.Rep[?]
[error]       .filter(_.userType === Member).result
但是下面的工作

.filter(_.userType === Member.asInstanceOf[UserType])

.filter(_.userType === (Member : UserType))

正如@Michal Tomanski所提到的,在使用
trait
/
case对象时存在一些问题。您需要做的是:

 sealed trait UserType {
    val code: Int
  }
  case object Member extends UserType {
    override val code: Int = 0
  }
  case object Anonymous extends UserType {
    override val code: Int = 1
  }

  object UserType {
    def byId(id: Int): UserType = id match {
      case Member.code => Member
      case Anonymous.code => Anonymous
      case _ => throw new IllegalArgumentException("...")
    }
  }

  implicit val enumColumnType = MappedColumnType.base[UserType, Int](
    e => e.code,
    i => UserType.byId(i)
  )
上面将允许您执行如下查询:

    UserTable
      .filter(_.userType === (Member :: UserType))
      .result
  sealed trait UserType {
    val code: Int
    // I added field below
    val base: UserType = this
  }
   UserTable
      .filter(_.userType === Member.base)
      .result
这正是@Michal Tomanski所指出的。你可以做一些小把戏来让它变得平滑一点

只需修改您的特征,如下所示:

    UserTable
      .filter(_.userType === (Member :: UserType))
      .result
  sealed trait UserType {
    val code: Int
    // I added field below
    val base: UserType = this
  }
   UserTable
      .filter(_.userType === Member.base)
      .result
然后您可以进行如下查询:

    UserTable
      .filter(_.userType === (Member :: UserType))
      .result
  sealed trait UserType {
    val code: Int
    // I added field below
    val base: UserType = this
  }
   UserTable
      .filter(_.userType === Member.base)
      .result
它可能比铸造稍好一些


除此之外-我会遵循@Michal Tomanski的答案(使用
枚举
),假设它对您的案例足够(也许带有
特征
/
案例对象
s的解决方案更灵活,但另一方面,您需要做更多的管道,正如在这个答案中可以看到的那样)。

抱歉,这是一个灵活的解决方案,我将强调这一点,而不仅仅是圆滑的标签。重复这一点: