Неявно добавить в коллекцию - PullRequest
0 голосов
/ 04 января 2019

У меня есть набор, и я хочу неявно добавить другое значение в конец этого набора при его вызове.

Например, мне нужно что-то вроде этого для работы:

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*/.

Я сейчас создаю суперпользователя, у которого есть доступ ко всем элементам функциональности на каждой странице, так что «роль» пользователя должна присутствовать в каждом наборе. Я не хочу делать это, вручную добавляя эту роль к каждому набору, потому что я хочу, чтобы она была масштабируемой и легко обслуживаемой, поэтому я надеялся на решение, которое просто добавит эту новую супер роль к каждому набору автоматически за кулисами. .

Я также открыт для неявных ответов, если они не изменяют исходные наборы, которые у меня уже есть.

Ответы [ 3 ]

0 голосов
/ 04 января 2019

Может быть, использование псевдонима типа будет приемлемо для вас?

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)
0 голосов
/ 04 января 2019

Как уже говорили другие, это может быть не очень хорошая идея, но если вам действительно нужно, вы можете попробовать свернуть свой собственный 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)
0 голосов
/ 04 января 2019

Я думаю, это то, что вы ищете:

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)
}
...