Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion, import required or not?

I write

object MyString {
  implicit def stringToMyString(s: String) = new MyString(s)    
}

class MyString(str: String) {
  def camelize = str.split("_").map(_.capitalize).mkString

  override def toString = str
}


object Parse {
  def main(args: Array[String]) {
    val x = "active_record".camelize
    // ...
  }
}

in my program. This causes a compiling error. After I inserted

  import MyString.stringToMyString

Then it works.

From Odersky's Programming in Scala I got that implicit conversion in the companion object of the source or expected target types don't need to be imported.

like image 275
Xenofex Avatar asked Dec 31 '10 09:12

Xenofex


People also ask

What are implicit conversions?

An implicit conversion sequence is the sequence of conversions required to convert an argument in a function call to the type of the corresponding parameter in a function declaration. The compiler tries to determine an implicit conversion sequence for each argument.

How do you use implicit conversions?

An implicit conversion from type S to type T is defined by an implicit value which has function type S => T , or by an implicit method convertible to a value of that type. Implicit conversions are applied in two situations: If an expression e is of type S , and S does not conform to the expression's expected type T .

What is an implicit conversion function Scala?

Implicit conversions in Scala are the set of methods that are apply when an object of wrong type is used. It allows the compiler to automatically convert of one type to another. Implicit conversions are applied in two conditions: First, if an expression of type A and S does not match to the expected expression type B.

How do you avoid implicit conversions in C++?

Keyword explicit tells compiler to not use the constructor for implicit conversion. For example declaring Bar's constructor explicit as - explicit Bar(int i); - would prevent us from calling ProcessBar as - ProcessBar(10); .


1 Answers

implicit conversion in the companion object of the source or expected target types don't need to be imported.

True enough. Now, the method camelize is defined on the class MyString, and, indeed, there is an implicit conversion to MyString inside its object companion. However, there is nothing in the code telling the compiler that MyString is the expected target type.

If, instead, you wrote this:

val x = ("active_record": MyString).camelize

then it would work, because the compiler would know you expect "active_record" to be a MyString, making it look up the implicit conversion inside object MyString.

This might look a bit restrictive, but it actually works in a number of places. Say, for instance, you had:

class Fraction(num: Int, denom: Int) {
    ...
    def +(b: Fraction) = ...
    ...
}

And then you had a code like this:

val x: Fraction = ...
val y = x + 5

Now, x does have a + method, whose expected type is Fraction. So the compiler would look, here, for an implicit conversion from Int to Fraction inside the object Fraction (and inside the object Int, if there was one, since that's the source type).

like image 145
Daniel C. Sobral Avatar answered Sep 28 '22 05:09

Daniel C. Sobral