Với nhiều bạn mới tìm hiểu về Scala thì đọc code trong một số thư viện hoặc chương trình opensource thì sẽ thấy xuất hiện rất nhiều keyword implicit. Vậy implicit là gì, đóng vai trò gì trong ngôn ngữ Scala. Chúng ta hãy cùng điểm qua 2 khái niệm implicit thông dụng và thường gặp nhất trong Scala

1. Implicit parameter

Chúng ta hãy cùng thử xem xét đoạn code sau:

def payLoan(amount: Float)(implicit interestRate: Float): Float = amount + amount * interestRate payLoan(2201100)(3.0F) // Success payLoan(2201100) // Will cause error

Ai cũng dễ dàng đoán được là lời gọi function payLoan thứ 2 sẽ sinh ra lỗi. Tuy nhiên đó không phải là lỗi nhắc function payLoan là currying function nên nếu chỉ gọi với 1 param thì cần có dấu “_” sau lời gọi function. Mà là lỗi như sau:

scala> payLoan(2201100) <console>:12: error: could not find implicit value for parameter interestRate: Float       payLoan(2201100)

Ta có thể thấy nguyên nhân là do keyword implicit ở đây. Thử sửa lại đoạn code và thêm 1 statement như sau vào trước function call

scala> implicit val interestRate: Float = 2.0F scala> payLoan(22001100) res2: Float = 6.60033E7

Có thể thấy ở đây khi sử dụng keyword implicit trước một param trong 1 function, và khi gọi hàm ta không cung cấp param đó cho function này thì Scala compiler sẽ tìm trong scope xung quanh khi gọi function một gía trị được khai báo implicit với type trùng với param và tự động thêm vào lời gọi hàm.  Ta xem xết tiếp đoạn code sau:

object Bank { implicit def interestRate(implicit isFriend: Boolean): Float = if (isFriend) 0.3F else 0.5F } import Bank.interestRate implicit val isFriend = true payLoan(2201100) // => res5: Float = 2861430.0

interestRate ở đây được gọi là implicit function. Có thể thấy là Scala compiler sẽ không chỉ tìm những  được khai báo implicit có giá trị khai báo sẵn dùng val mà tìm luôn những implicit function có thể trả về trực tiếp giá trị với type trùng với type của implicit parameter.

Implicit parameter là một tính năng rất mạnh, khiến cho chương trình Scala trở nên flexible hơn rất nhiều, ta không cần phải chỉ rõ biến truyền vào có giá trị là gì, mà để Scala compiler tự tìm giá trị hợp lý trong context gọi function. Tuy nhiên nếu lạm dụng sẽ khiến code trở nên khó hiểu và khó debug hơn.

2. Implicit conversion

Implicit conversion là một tính năng hết sức thú vị và là một trong những lí do tạo nên tính flexible cho Scala và khiến ngôn ngữ này là một ngôn ngữ ưa thích để viết các DSL (Domain Specific Language). Ta hãy cùng xem xet một ví dụ đơn giản sau, trong Scala các gía trị thuộc type Int không có operator ‘**’ để tính luỹ thừa

scala> 3 ** 4 <console>:11: error: value ** is not a member of Int       3 ** 4

Nhưng giả sử bạn muốn tính luỹ thừa dùng operator ‘**’ giống như trong Python thì nên làm thế nào?  Scala cũng ko tính mở như Ruby để có thể mở lại class Int và thêm 1 method mới vào nhưng Implicit Conversion sẽ giúp ta thực hiện điều này:

scala> implicit class Utils (val x: Int) {     | def **(y: Int) = scala.math.pow(x, y)     | } defined class Utils scala> 3 ** 5 res0: Double = 243.0

Class Utils ở đây được gọi là một implicit class và đóng vai trò thực hiện implicit conversion. Có thể thấy là khi một method hoặc một trường không tồn tại (ở đây là method **) được gọi đến một object (3) thì Scala Compiler sẽ tìm kiếm trong scope hiện tại một implicit class có thể nhận object đó làm parameter và bên trong class đó có định nghĩa của method hoặc trường không tồn tại trên.

Thư viện standard của Scala cũng cung cấp rất nhiều implicit conversion có sẵn, chúng ta chỉ cần import vào code của mình và dùng luôn. Ví dụ để có thể so sánh 2 tuple, ta có thể xử lý như sau:

scala> (1, 2, 3) < (1, 2, 4) // Obviously, this will cause error <console>:20: error: value < is not a member of (Int, Int, Int) (1, 2, 3) < (1, 2, 4) scala> import scala.math.Ordering.Implicits._ // Import implicit conversion for comparing 2 tuples import scala.math.Ordering.Implicits._ scala> (1,2,3) < (1,2,4) res7: Boolean = true

Có thể thấy, sử dụng Implicit Conversion, ta có thể thêm method hoặc property vào instance của các class đã được khai báo trước (điều tưởng như không thể với một static language như Scala), điều này như đã nói khiến Scala trở thành một ngôn ngữ rất flexible (gần như một dynamic language) và rất mạnh trong việc viết các DSL. Tuy nhiên, nếu lạm dụng cũng như với implicit parameter, sẽ khiến code trở nên khó hiểu và xảy ra tình trạng chỉ có người viết code mới hiểu được ?

3. Kết

Hầu như bất kỳ thư viện open source Scala nào hiện tại ít nhiều sử dụng implicit parameter và implicit conversion. Điều này nói lên sự hữu dụng của implicit, một tính năng mà nếu năm được thuần thục sẽ nâng trình độ của một Scala developer lên một tầm cao mới.

Tham khảo:

http://docs.scala-lang.org/tutorials/tour/implicit-parameters.html

http://docs.scala-lang.org/tutorials/tour/implicit-conversions.html