diff --git a/_tour/implicit-conversions.md b/_tour/implicit-conversions.md index c7f58d8009..cf93a062f2 100644 --- a/_tour/implicit-conversions.md +++ b/_tour/implicit-conversions.md @@ -38,9 +38,69 @@ In the second case, a conversion `c` is searched for, which is applicable to `e` An example is to compare two strings `"foo" < "bar"`. In this case, `String` has no member `<`, so the implicit conversion `Predef.augmentString("foo") < "bar"` is inserted. (`scala.Predef` is automatically imported into all Scala programs.) -### How are implicit conversions selected? +### How are implicit conversions brought into scope? ### -See this [Scala FAQ Answer](https://docs.scala-lang.org/tutorials/FAQ/index.html#where-does-scala-look-for-implicits). +{% tabs implicit-conversion-scope class=tabs-scala-version %} +{% tab 'Scala 2' %} +In Scala 2, an implicit conversion is brought into scope by importing from the object that defined it, (e.g. `Conversions` in this case). If the implicit conversion is in the companion object of the argument type, (e.g. `Student` in this case), then no import is necessary. + +```scala +import scala.language.implicitConversions // required to define an implicit conversion + +case class Student(name: String) +object Student { + implicit def fromStudentToInt(student: Student): Int = student.name.length +} + +object Conversions { + implicit def fromStringToStudent(name: String): Student = Student(name) +} + +import Conversions._ +object Usage { + def main(args: Array[String]) = { + val reginald: Student = "Reginald" // applies the conversion Conversions.fromStringToStudent + println(reginald + 2) // applies the conversion Student.fromStudentToInt + } +} +``` +{% endtab %} +{% tab 'Scala 3' %} +In Scala 3, an implicit conversion is brought into scope by either importing `given` or the named conversion from the object that defined it, (e.g. `Conversions` in this case). + +Note that as of Scala 3, implicit conversions cannot be brought into scope anymore by means of a wildcard import (`*`). + +Given the example: + +```scala +case class Student(name: String): + def printName: Unit = println(name) +object Student: + given Conversion[Student, Int] = _.name.length + +object Conversions: + given fromStringToStudent: Conversion[String, Student] = Student(_) +``` + +The following imports would bring the `Conversion[String, Student]` into scope: + - `import Conversions.given` + - `import Conversions.{given Conversion[String, Student]}` + - `import Conversions.fromStringToStudent` + +If the implicit conversion is in the companion object of the argument type, (e.g. `Student` in this case), then no import is necessary. + +```scala +import Conversions.given +object Usage: + @main def run = + val reginald: Student = "Reginald" // applies the Conversion[String, Student] + println(reginald + 2) // applies the Conversion[Student, Int] +``` +{% endtab %} +{% endtabs %} + +Further reading: + - [Where does Scala look for implicits? (on StackOverflow)](https://docs.scala-lang.org/tutorials/FAQ/index.html#where-does-scala-look-for-implicits). ### Beware the power of implicit conversions