Scala – Extractor

Scala extractor là một object có một phương thức được gọi là unapply. Phương thức unapply khớp một giá trị và tách nó ra. Extractor cũng định nghĩa phương thức apply xây dựng các giá trị.

Hãy cùng xem ví dụ sau đây dùng để lấy first name và last name sử dụng khoảng trống là ký tự để tách.

object firstName {
  def main(args: Array[String]) {
    println("Apply method : " + apply("Steve", "Smith"));
    println("Unapply method : " + unapply("Steve Smith"));
    println("Unapply method : " + unapply("Rob"));
  }

  def apply(fname: String, lname: String): String = {
    fname + " " + lname
  }

  def unapply(s: String): Option[(String, String)] = {
    val pts = s split " "
    if (pts.length == 2) {
      Some(pts(0), pts(1))
    } else {
      None
    }
  }
}

Object firstName định nghĩa 2 phương thức là apply và unapply. apply phương thức chuyển đổi thành một object bằng cách nhận các tham số xác định trong dấu ngoặc đơn và tạo ra giá trị được xác định trong phương thức. fname và lname được nối lại với nhau bằng một khoảng trống ở giữa, được trả về cho phương thức.

Phương thức unapply trả về một firstName object trong một extractor và tách các tham số xác định trong phương thức. Như ở trên thì hàm unapply nhận vào một tham số String và tách String này bằng cách dựa theo các dấu cách trong String, và trả về một Option với kiểu pair của String. Kết quả sẽ là pair của String, nếu nó có thể tách ra được fname và lname dựa trên String truyền vào, nếu không thì sẽ trả về None.

Sau đây là kết quả chúng ta sẽ nhận được khi chạy

Apply method : Steve Smith
Unapply method : Some((Steve,Smith))
Unapply method : None

Pattern matching

Nếu instance của class là một danh sách không hoặc nhiều tham số, compiler sẽ gọi phương thức apply trên instance. Phương thức apply có thể được định nghĩa trên cả class và object.

Hãy xem ví dụ bên dưới đây

case class Address(city: String, state: String)
case class Student(name: String, address: Seq[Address])

object City {
  def unapply(s: Student): Option[Seq[String]] =
    Some(
      for (c <- s.address)
        yield c.state
    )
}

class StringSeqContains(value: String) {
  def unapply(in: Seq[String]): Boolean =
    in contains value
}

object PatternMatch {
  def main(args: Array[String]) {
    val stud = List(Student("Harris", List(Address("LosAngeles", "California"))),
      Student("Reena", List(Address("Houston", "Texas"))),
      Student("Rob", List(Address("Dallas", "Texas"))),
      Student("Chris", List(Address("Jacksonville", "Florida"))))

    val Texas = new StringSeqContains("Texas")
    val students = stud collect {
      case student @ City(Texas()) => student.name
    }
    println(students)
  }
}

Trong ví dụ trên chúng ta định nghĩa 2 class là Student và Address. class Student name và địa chỉ address, còn Address chứa city và state.

Trong object City chúng ta định nghĩa một unapply phương thức để lấy các state từ list của address. Trong PatternMatch object chúng ta tạo object Student và address. Chúng ta tìm kiếm tên của student mà có city là Texas, với pattern được kiểm tra là phù hợp.

Sau đây là kết quả chúng ta sẽ nhận được sau khi chạy

List(Reena, Rob)

 

You May Also Like

About the Author: Nguyen Dinh Thuc

Leave a Reply

Your email address will not be published.