通过隐式转换覆盖Int上的算术运算符

时间:2010-12-14 20:20:07

标签: scala

说出来,出于美学原因,我希望能够写下:

3 / 4

并且/是一个类的方法,存在从Int到的隐式转换,例如:

class Foo(val i: Int) {
  def /(that: Int) = // something
}

implicit def intToFoo(i: Int) = new Foo(i)

这是否可能,即是否可以“禁用”Int?

上的/方法

3 个答案:

答案 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提取器而不是IntString的隐式转换,您实际上可以从字符串中检索整数值,当且仅当它是可转换的且当然立即使用它。显然,如果你不喜欢这个命名,你可以把它改成更不引人注目的东西,但是如果你真的想要进行网址匹配,你可能不应该隐式转换所有内容。