Berikut adalah beberapa alasan untuk menggunakan metode sederhana yang menyenangkan implicitly
.
Untuk memahami / memecahkan masalah Tampilan Tersirat
Tampilan Tersirat dapat dipicu ketika awalan suatu seleksi (pertimbangkan misalnya, the.prefix.selection(args)
tidak mengandung anggota selection
yang berlaku untuk args
(bahkan setelah mencoba untuk mengkonversi args
dengan Tampilan Tersirat). Dalam kasus ini, kompiler mencari anggota tersirat, ditentukan secara lokal dalam lingkup saat ini atau melampirkan, diwariskan, atau diimpor, yang merupakan Fungsi dari jenis yang the.prefix
ke jenis dengan selection
metode implisit yang ditetapkan, atau setara.
scala> 1.min(2) // Int doesn't have min defined, where did that come from?
res21: Int = 1
scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>
scala> res22(1) //
res23: AnyRef{def min(i: Int): Int} = 1
scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt
Tampilan Tersirat juga dapat dipicu ketika ekspresi tidak sesuai dengan Tipe yang Diharapkan, seperti di bawah ini:
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
Di sini kompiler mencari fungsi ini:
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
Mengakses Parameter Tersirat Diperkenalkan oleh Batas Konteks
Parameter implisit merupakan fitur Scala yang lebih penting daripada Tampilan Implisit. Mereka mendukung pola kelas tipe. Pustaka standar menggunakannya di beberapa tempat - lihat scala.Ordering
dan bagaimana menggunakannya SeqLike#sorted
. Parameter implisit juga digunakan untuk melewati manifest Array, dan CanBuildFrom
instance.
Scala 2.8 memungkinkan sintaks steno untuk parameter implisit, yang disebut Batas Konteks. Secara singkat, metode dengan parameter tipe A
yang memerlukan parameter tipe implisit M[A]
:
def foo[A](implicit ma: M[A])
dapat ditulis ulang sebagai:
def foo[A: M]
Tapi apa gunanya melewati parameter implisit tetapi tidak menamainya? Bagaimana ini bisa berguna ketika menerapkan metode ini foo
?
Seringkali, parameter implisit tidak perlu dirujuk secara langsung, itu akan diteruskan sebagai argumen implisit ke metode lain yang disebut. Jika diperlukan, Anda masih bisa mempertahankan tanda tangan metode singkat dengan Bound Konteks, dan panggilan implicitly
untuk mewujudkan nilai:
def foo[A: M] = {
val ma = implicitly[M[A]]
}
Melewati sebagian parameter implisit secara eksplisit
Misalkan Anda memanggil metode yang cukup mencetak seseorang, menggunakan pendekatan berbasis kelas tipe:
trait Show[T] { def show(t: T): String }
object Show {
implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }
def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}
case class Person(name: String, age: Int)
object Person {
implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
}
}
val p = Person("bob", 25)
implicitly[Show[Person]].show(p)
Bagaimana jika kita ingin mengubah cara nama itu dihasilkan? Kami dapat secara eksplisit memanggil PersonShow
, secara eksplisit melewati alternatif Show[String]
, tetapi kami ingin kompiler untuk lulus Show[Int]
.
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)