说出来,出于美学原因,我希望能够写下:
3 / 4
并且/是一个类的方法,存在从Int到的隐式转换,例如:
class Foo(val i: Int) {
def /(that: Int) = // something
}
implicit def intToFoo(i: Int) = new Foo(i)
这是否可能,即是否可以“禁用”Int?
上的/方法答案 0 :(得分:7)
简而言之:不,你不能。
只有在您尝试调用尚不存在的方法时才会发生隐式解析。
更“惯用”的解决方案是创建自己的伪数字类型,如:
case class Rational(a: Int, b: Int) {
// other methods
}
val foo = Rational(3, 4)
或
case class Path(value: String) {
def /(other: String): Path = ...
}
val p = Path("3") / "4"
答案 1 :(得分:2)
有没有像
这样的原因trait PathElement[T] { val value: T }
case class IntElement(value: Int) extends PathElement[Int]
case class StringElement(value: String) extends PathElement[String]
case class Path(parts: Seq[PathElement[_]]) {
def /(other: Path): Path = copy(parts = parts ++ other.parts)
}
object Path {
def apply(part: PathElement[_]): Path = Path(List(part))
implicit def int2path(i: Int): Path = Path(IntElement(i))
implicit def str2path(s: String): Path = Path(StringElement(s))
}
对你不起作用?这将允许您编写,例如,
import Path._
"foo" / 3 / 4 / "bar"
这是有效的,因为String没有自己的/
方法,因此第一个"foo"
被隐式转换为Path
。如果您使用Path
开始Int
,则必须明确转换它,但您可以免费获得任何其他Int
。
答案 2 :(得分:1)
我当然只能猜测你真正想要实现的目标,但我认为你不仅要匹配具体的URL,还要从给定的字符串中提取信息。例如。当给定"/foo/21"
时,您不仅要知道这与某些"foo" / 21
匹配,而且您想要使用值21来执行某些操作。
我发现Lift中的URI匹配过程非常有用,所以可能适合您的用例。 (当然,我正在使用一个非常简化的版本。)这是通过列表完成的,这使匹配变得更容易,但这也意味着你必须使用::
而不是/
。
但这不是重点:我想要展示的是不使用隐式转换和提取器的强大功能
的优势object AsInt {
def unapply(i: String): Option[Int] = try {
Some(i.toInt)
} catch {
case e: java.lang.NumberFormatException => None
}
}
def matchUrl(url: String) = {
val req:List[String] = url.split('/').toList.drop(1)
req match {
case "foo" :: "bar" :: Nil => println("bar")
case "foo" :: AsInt(i) :: Nil => println("The square is " + i*i)
case "foo" :: s :: Nil => println("No int")
case _ => println("fail")
}
}
matchUrl("/foo/21")
matchUrl("/foo/b")
matchUrl("/foo/bar")
matchUrl("/foobar")
// prints:
// The square is 441
// No int
// bar
// fail
简而言之,使用AsInt
提取器而不是Int
到String
的隐式转换,您实际上可以从字符串中检索整数值,当且仅当它是可转换的且当然立即使用它。显然,如果你不喜欢这个命名,你可以把它改成更不引人注目的东西,但是如果你真的想要进行网址匹配,你可能不应该隐式转换所有内容。