隐式添加到集合

时间:2019-01-04 12:26:32

标签: scala implicit

我有一个Set,我想在调用Set时在该Set的末尾隐式添加另一个值。

例如,我需要这样的东西才能工作:

implicit def addToSet(set: Set[Int]) = set + 4
val s = Set(1, 2, 3)
println(s) // Set(1, 2, 3, 4)

用例:

我正在建立一个网站(使用PlayFramework),并且我拥有大约20-30套角色,分别对应于不同的功能。对于每个页面,只有某些角色才能访问某些功能,因此每次我需要检查角色特权(以伪代码:if(role.canAccess(/*name of page*/)))时,我都有一些功能,该特权检查用户是否按原样登录的角色包含在与/*name of page*/相对应的集合中。

我现在正在创建一个超级用户,该用户可以访问每个页面上的所有功能,因此用户的“角色”必须位于每个Set中。我不想通过手动将此角色添加到每个Set来执行此操作,因为我希望此角色具有可伸缩性且易于维护,因此我希望找到一种解决方案,将这种新的超级角色自动添加到幕后的每个Set中

只要他们不修改我已经拥有的原始Set,我也可以接受非隐式答案。

3 个答案:

答案 0 :(得分:2)

我认为这就是您要寻找的东西

trait Implicits {
  implicit class AddIntoSet[T](set: Set[T]) {
    def add(t: T): Set[T] = {
      set.+(t)
    }
  }
}


object Solution1 extends App with Implicits {
  val s = Set(1, 2, 3)
  println(s.add(4)) // Set(1, 2, 3, 4)
}

答案 1 :(得分:1)

就像其他人说的那样,这可能不是一个好主意,但如果确实需要,您可以尝试对自己的Set对象进行一些修改:

import scala.collection.generic.SetFactory
import scala.collection.{GenSet, Set, immutable}

object CustomSet extends SetFactory[Set]{
  def newBuilder[A] = immutable.Set.newBuilder[A]

  def apply[T](elems: T*)(implicit extra: T): Set[T] = {
    val orig: Set[T] = super.apply(elems).flatten
    val withExtra: Set[T] = orig union GenSet(extra)
    withExtra
  }
}

implicit val extraInt: Int = 4
implicit val extraStr: String = "c"

val myNumNewSet: Set[Int] = CustomSet(1,2,3)
val myStrNewSet: Set[String] = CustomSet("a", "b")

这些将返回:

scala> val myNumNewSet: Set[Int] = CustomSet(1,2,3)
myNumNewSet: scala.collection.Set[Int] = Set(1, 2, 3, 4)

scala> val myStrNewSet: Set[String] = CustomSet("a", "b")
myStrNewSet: scala.collection.Set[String] = Set(a, b, c)

答案 2 :(得分:0)

也许您可以使用类型别名?

object Roles {
  type Role = Int //Optionally you can use type tagging to make it more type-safe
  type Roles = Set[Role]

  val SuperRole = 4

  def apply(roles: Role*): Roles = {
    Set(SuperRole) ++ roles
  }
}



println(Roles(1,2,3)) // Set(4, 1, 2, 3)
println(Roles() ++ Set(5,6)) // you can also use all methods from Set

这还有一个优势,那就是,如果您在角色以外的其他范围内使用它,则不会造成干扰:

val idsOfUsers = Set(10,12,22) // Set(10, 12, 22)
val roles = Roles(10,12,22) //Set(4, 10, 12, 22)