我想编写一个API,允许我轻松创建像
这样的分层键/ foo / bar / baz
为此,我创建了以下类:
sealed trait Key {
def path: String
def /(key: String): Node = Node(this, key)
}
case object Root extends Key {
override def path: String = ""
}
final case class Node(parent: Key, key: String) extends Key {
override def path: String = s"${parent.path}/$key"
}
它完美无缺:
Root / "foo" / "bar"
现在,我还希望能够包含'占位符'像这样:
Root / "foo" / %
然后返回一些东西,当一个字符串被应用时,返回一个Key
对象,替换给定的值,即
(Root / "foo" / %)("bar") == Root / "foo" / "bar"
请记住,这应该适用于n级,如下所示:
Root / % / "foo" / % / "bar"
答案 0 :(得分:2)
这可能效率不高,但它符合您的要求。
请注意,回答我自己的评论,我决定
(Root / % / "foo" / % / "bar")("baz") == (Root / % / "foo" / "baz" / "bar")
但是要改变以获得不同的结果并不多。
object % // only for nicer API
trait Slashable[T <: Slashable[T]] {
def /(key: String): T
def /(p: %.type): PlaceHeld[T] = PlaceHeld[T](str => /(str))
}
case object Root extends Key {
override def path: String = ""
}
sealed trait Key extends Slashable[Key] {
def path: String
def /(key: String): Node = Node(this, key)
}
final case class Node(parent: Key, key: String) extends Key {
override def path: String = s"${parent.path}/$key"
}
case class PlaceHeld[T <: Slashable[T]](replace: String => T) extends Slashable[PlaceHeld[T]]{
def /(key: String) = PlaceHeld(str => replace(str)./(key))
def apply(key: String) = replace(key)
}
修改强>
您可能希望通过简单(包装)Seq
替换您的基本类型(没有占位符):
case class Key(pathSeq: Seq[String]) extends Slashable[Key] {
def path = pathSeq.mkString("/")
def /(key: String) = Key(pathSeq :+ key)
}
object Root extends Slashable[Root] {
def path = "" //this is because we cannot do
def /(key: String) = Key(Seq(key)) //Root extends Key(Seq())
}