Scala implicit keywords

  Scala's implicit keyword includes two aspects: implicit parameters and implicit conversion .
  Implicit parameters: declare some variables as implicit parameters, and declare some method parameters as supporting implicit parameters. When calling the method, if the parameter is not passed, then you can use the implicit parameters.
  Implicit conversion: first provide some type conversion capabilities (through implicit classes and implicit methods), and then when calling certain methods, when the types of certain objects do not match, you can use the corresponding implicit conversion to convert the object Types of.

Restrictions on implicit usage

Search range

When you need to search for implicit objects, implicit methods, and implicit classes, the scope of the search is:
1. First search in the current code scope
2. If the search fails in the current scope, it will be in the scope of the implicit parameter type
The scope of the search type refers to all the associated modules associated with the type. The search range of an implicit entity type T is as follows:
(1) If T is defined as T with A with B with C, then A, B and C are both parts of T. During the implicit analysis of T, their associated objects are searched.
(2) If T is a parameterized type, then the type parameter and the part associated with the type parameter are both counted as T Part, such as the implicit search of List [String] will search the associated objects of List and the associated objects of String
(3) If T is a singleton type pT, that is, T belongs to a certain p object, then this p object also Will be searched
(4) If T is a type injection S # T, then both S and T will be searched

One-time rule

When the compiler needs to use implicit definition, it will only try to convert once, that is, the compiler will never rewrite x + y to convert1 (convert2 (x)) + y.

Unambiguous

For implicit parameters, if there are two variables of this type in the search range, the compiler reports an error.
For implicit conversion, if there are two implicit conversions from type A to type B in the search range, the compiler reports an error.

Implicit parameter

When declaring a method, add the implict modifier in front of the parameter. When the method is called, if the parameter is not passed, the compiler will go to the above search range to find the implicit parameter. If it exists, use the found implicit Parameters as parameter values. You can refer to the following example:

package net.scala.test1.implicit_

/*
隐式参数Test
*/
object ImplicitValueTest {
  def showStr(implicit name: String) = println(name)
  def main(args: Array[String]): Unit = {
  }
}

/*
隐式参数的例子,来源于 https://docs.scala-lang.org/zh-cn/tour/implicit-parameters.html
*/
abstract class Monoid[A] {
  def add(x: A, y: A): A
  def unit: A
}

object ImplicitValueTest2 {
  implicit val stringMonoid: Monoid[String] = new Monoid[String] {
    def add(x: String, y: String): String = x concat y
    def unit: String = ""
  }

  implicit val intMonoid: Monoid[Int] = new Monoid[Int] {
    def add(x: Int, y: Int): Int = x + y
    def unit: Int = 0
  }

  def sum[A](xs: List[A])(implicit m: Monoid[A]): A =
    if (xs.isEmpty) m.unit
    else m.add(xs.head, sum(xs.tail))

  def main(args: Array[String]): Unit = {
    println(sum(List(1, 2, 3)))       // uses IntMonoid implicitly
    println(sum(List("a", "b", "c"))) // uses StringMonoid implicitly
  }
}

Implicit conversion

When is implicit conversion used?

Implicit conversion will be used in two cases:
① When the method is called, the parameter type passed is different from the parameter type declared by the method, the compiler will search for implicit conversion under the search scope, and convert the passed parameter into the method declaration needs type.
② When calling a method, if the object does not have the method, the compiler will search for implicit conversions in the search range, and convert the object calling the method into an object of the type of the method.

What are the implicit conversions?

Implicit methods and implicit classes.

The following code shows the conversion method parameters using implicit conversion:

package net.scala.test1.implicit_
object ImplicitObject1 {
  implicit def doubleToInt(x: Double) = x toInt
}
/*
隐式转换方法参数
使用隐式方法转换
*/
object ImplicitConvertTest1 {
  def showInt(i: Int) = println("i is " + i)
  def main(args: Array[String]): Unit = {
    import net.qingtian.scala.test1.implicit_.ImplicitObject1._
    showInt(1.1)
    val ii: Int = 1.2
    println("ii is " + ii)
  }
}

The following code shows an object that uses implicit conversion to call a method that does not exist:

package net.scala.test1.implicit_
class Speaker {
  def speak(str: String) = println("Speaker说:" + str)
}
class Aminal
object ImplicitObject2 {
  implicit class StringImprovement(val s: String) { //隐式类
    def increment = s.map(x => (x + 1).toChar)
  }
  implicit def toSpeaker(s: Aminal) = new Speaker
}
object ImplicitConvertTest2 {
  def main(args: Array[String]): Unit = {
    import net.scala.test1.implicit_.ImplicitObject2._
    // 通过隐式类进行转换
    // 把字符串"abcde"隐式转换成ImplicitObject2.StringImprovement
    println("abcde".increment)
    // 通过隐式方法转换
    // 把rabbit对象转换成Speaker对象使用
    val rabbit = new Aminal
    rabbit.speak("hello world")
  }
}

When constructing a Map object, the-> symbol used is implicit conversion.

Map(1 -> "One", 2->"Two",3->"Three")

The values ​​in the Map are implicitly converted into ArrowAssoc objects, and the-> method of ArrowAssoc objects generates tuples. -> The implementation of the method is as follows:

def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y)
Published 162 original articles · praised 58 · 90,000 views

Guess you like

Origin blog.csdn.net/ThreeAspects/article/details/105405015