Overriding arithmetic operators on Int via implicit conversions

Say that for aesthetic reasons I want to write:

3 / 4 

and have an / - method in the class that there is an implicit conversion from Int to, for example:

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

Is this possible, i.e. Is it possible to "disable" the / method on Int?

+4
source share
3 answers

In short: no, you cannot.

Implicit permission will only be executed when trying to call a method that does not yet exist.

A more “idiomatic” solution would be to create your own pseudo-number, for example:

 case class Rational(a: Int, b: Int) { // other methods } val foo = Rational(3, 4) 

or

 case class Path(value: String) { def /(other: String): Path = ... } val p = Path("3") / "4" 
+7
source

Is there a reason that something like

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

won't work for you? This will allow you to write, for example,

 import Path._ "foo" / 3 / 4 / "bar" 

This works because String does not have its own / method, so the first "foo" implicitly converted to Path . If you started with Path with Int , you would need to explicitly convert it, but you would get any other Int for free.

+2
source

Of course, I can only guess what you really want to achieve, but I assume that you simply do not want to map specific URLs, and also extract information from the given strings. For example. when specifying "/foo/21" you just don't want to know that this matches some "foo" / 21 , but you want to do something with a value of 21.

Ive found that the URI matching process in Lift is very useful, so maybe this is suitable for your use case. (Of course, I am using a very simplified version). It is made using lists, which simplifies matching, but it also means that you need to use :: instead of / .

But this is not the main thing: what I want to show is the advantage of using implicit transformations and extractor power

 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 

In short, using an AsInt extractor instead of implicitly converting Int to String , you can actually extract an integer value from a string if and only if it is convertible and, of course, use it immediately. Obviously, if you don't like the naming convention, you can change it to something more unobtrusive, but if you really want to perform URL mapping, you probably shouldn't completely convert everything.

+1
source

All Articles