0

我注意到我的代码中的重复模式,并认为这可能是尝试结构类型的一个好主意。我已经阅读了这一章;-),但我无法完全理解它。考虑以下代码:

  def link(user: User, group: Group) = {
    UserGroupLinks.insert((user.id, group.id))
  }

  def link(group: Group, role: Role) = {
    GroupRoleLinks.insert((group.id, role.id))
  }

  def link(user: User, role: Role) = {
    UserRoleLinks.insert((user.id, role.id))
  }

我如何将它组合成类似的东西:

def link(A <: ...something with an id, B<:... something with and id) = {
  (A, B) match {
    case (u: User,  g: Group) =>  UserGroupLinks.insert((user.id, group.id))
    case (g: Group, r: Role)  =>  GroupRoleLinks.insert((group.id, role.id))
    case (u: User,  r: Role)  =>  UserRoleLinks.insert((user.id, role.id))
    case _ =>
  }
}
4

3 回答 3

2

对于结构类型,它将是这样的:

type WithId = {def id:Int}

def link(a:WithId, b:WithId) =
  (a, b) match {
    case (u:User, g:Group) => UserGroupLinks.insert(u.id -> g.id)
    case _ =>
  }

编辑

您可以走得更远,让编译器帮助您选择正确的插入器。为此,您需要在插入器上引入一个特征:

trait WithInsert[A, B] {
  def insert(x: (Int, Int)): Unit
}

然后在您的插入对象上执行以下操作:

object UserGroupLinks extends WithInsert[User, Group]

您可以在伴随对象上定义默认值

object WithInsert {
  implicit val ug = UserGroupLinks
  implicit val gr = GroupRoleLinks
}

我们仍然可以使用该WithId类型,尽管在大多数情况下我建议使用 trait

type WithId = { def id: Int }

您的链接方法将如下所示:

def link[A <: WithId, B <: WithId](a: A, b: B)(implicit inserter: WithInsert[A, B]) =
  inserter.insert(a.id -> b.id)

如您所见,链接方法期望 aWithInsert[A, B]可用。它将在 的伴生对象中找到合适的对象WithInsert

这意味着您现在可以像这样简单地调用您的方法:

link(user, group)
link(group, role)
于 2013-02-25T18:58:55.423 回答
0

尝试

type T = { val id: String }

def link(obj1 : T, obj2: T) = {
   // You got 
   println(" obj1.id = %s obj2.id = %s".format(obj1.id, obj2.id))  
} 
于 2013-02-26T09:06:10.533 回答
0

这是我一直在寻找的简单解决方案:

  def link[A <: { def id: Long }, B <: { def id: Long }](a: A, b: B) = {
    (a, b) match {
      case (u: User, g: Group) => UserGroupLinks.insert((u.id, g.id))
      case (g: Group, r: Role) => GroupRoleLinks.insert((g.id, r.id))
      case (u: User, r: Role)  => UserRoleLinks.insert((u.id, r.id))
      case _ => ???
    }
  }

编译器允许的地方:

case class XX(id:  Long)
case class YY(id:  Long)
case class ZZ(idz: Long)

link(XX(22), YY(33))

但不是:

link(XX(22), ZZ(33))
于 2013-02-26T01:14:43.737 回答