Scala Basic - Implicit

Implicit


Magic?!


1. Assign parameter with a wrong type?!

var a: String = "Hello"
a = "See you" 
a = 1       //???

2. Invoke a missing function?!

class A {def log(): Unit = "logs...balabala"}
val a = new A()
a.log()
a.show()        //???

3. Invoke function without enough parameters?!

def f(a: Int)(b: Int): Int
val a = f(1)(2)
val b = f(1)        //???

Overview

  • What is Implicit in Scala?

  • Definition

  • When to use Implicit?

  • Importing Implicits

  • Rules for Implicit Conversions

  • Extension

    • How to give the default value of parameters?
    • How to restrict the type parameter?

What is Implicit in Scala?


Implicits are a powerful, code-condensing feature of Scala

It is usually used in type conversion and function/class parameter and happens in compilation phase.


Scala Basic - Implicit_第1张图片

Definition


1. Variable

implicit val a:Int = 1

2. Method

implicit def int2Str(v:Int):String = v.toString

3. Class

implicit class Show(a: A) {
    def show(): Unit = println("This is an implicit show method.")
}

4. Method Parameter

def sort[A](l:List[A])(implicit order:Ordering[A])

5. Class Parameter

class Ages(ages:List[Int])(implicit order:Ordering[Int])

6. Type Parameter

def sort[A:Ordering](l:List[A])

When to use Implicit?


1. Type mismatch

If the type of an expression differs from the expected type

var a: String = "Hello"
a = 1    

implicit def int2str(v: Int): String = v.toString

2. Access nonexistent member

If an object accesses a nonexistent member

class A {def log(): Unit = "logs...balabala"}
val a = new A()
a.show()

implicit class Show(a: A) {
    def show(): Unit = println("This is implicit show method.")
}

3. Missing parameters

If an object invokes a method whose parameters don't match the give arguments

def f(a: Int)(implicit b: Int): Int
val a = f(1)(2)
val b = f(1)

implicit val b: Int = 0

Importing Implicits


1. Implicit functions or classes in the companion object of the source or target type

object AccessNonexistentMember {
  def main(args: Array[String]): Unit = {
    val a = new A()
    a.show()
  }
}
class A { def log(): Unit = ???}
object A {
  implicit class Show(a: A) {
    def show(): Unit = println("This is implicit show method.")
  }
}

2. Implicit functions or classes that are in scope

object TypeMismatch {
  def main(args: Array[String]): Unit = {
    import IntConversion.int2str
    var a: String = "Hello"
    a = 1
  }
}
object IntConversion {
  implicit def int2str(v: Int): String = v.toString
}

Rules for Implicit Conversions


1. Only trigger by error

No implicit conversion is used if the code compiles without it

  • Type mismatch
  • Access nonexistent member
  • Missing parameters

2. Only one match

Ambiguous conversions are an error. For example, if both convert1(a) * b and convert2(a) * b are valid, the compiler will report an error.


3. Only do once

The compiler will never attempt multiple conversions, such as convert1(convert2(a)) * b

case class Name(v: String)
object Name {
  implicit def str2Name(v: String): Name = Name(v)
}
object Test {
  implicit def int2Str(v: Int): String = v.toString
}
val me: Name = "Yaxin"
val age: String = 18

val num: Name = 89757  //error: type mismatch(Compilation Failed)

Extension

  • How to give the default value of parameters?
  • How to restrict the type parameter?

How to give the default value of parameters?

def sort[A](l: List[A])(implicit order: Ordering[A]) = l.sorted
sort(List(3, 1, 2))
sort(List(3, 1, 2))(implicitly[Ordering[Int]].reverse)
def f(a: Int)(implicit b: Int): Unit = println(s"f: a is $a, b is $b")
def g(a: Int)(b: Int = 0): Unit = println(s"g: a is $a, b is $b")

How to restrict the type parameter?

def compare[A: Ordering](x: A, y: A): Int = implicitly[Ordering[A]].compare(x, y)
compare(1, 2)
compare(Age(1), Age(3)) //No implicit Ordering defined for Age (Compilation Failed)

你可能感兴趣的:(Scala Basic - Implicit)