Scala – Type Bound

Trong phần trước tôi đã giới thiệu cho bạn về Variance. Bạn nên đọc phần này trước khi vào bài viết này.

Typy Bound là các giới hạn trên các Type parameter hoặc Type Variable. Bằng việc sử dụng Type Bound, chúng ta có thể định nghĩa giới hạn Type Variable.

Ưu điểm của Type Bound

Type Bound mang đến cho chúng ta những lợi ích sau:

  • Phát triển ứng dụng Type-safe

Type Bound

Scala hỗ trợ những Type Bound sau cho Type Variable

  • Scala Upper Bounds
  • Scala Lower Bounds
  • Scala View Bounds

Scala Upper Bound

Trong Scala, chúng ta có thể định nghĩa Upper Bound trên Type Parameter như hình bên dưới đây:

Ở đây thì T là một Type Parameter và S là một Type. Bằng việc khái báo Upper Bound T <: S nghĩa là Type Parameter hay T này phải giống với Type của S hoặc sub-type của S

Ví dụ

[T <: Ordered[T]]

Ở đây chúng ta đã định nghĩa Upper Bound từ Type Parameter T đến Ordered[T]. Do đó T phải là Ordered hoặc sub-type của Ordered.

Tiếp theo hãy cùng xem đoạn code sau đây để hiểu rõ hơn về Type Bound

class Animal
class Dog extends Animal
class Puppy extends Dog

class AnimalCarer{
  def display [T <: Dog](t: T){
    println(t)
  }
}

object ScalaUpperBoundsTest {
  def main(args: Array[String]) {

    val animal = new Animal
    val dog = new Dog
    val puppy = new Puppy

    val animalCarer = new AnimalCarer

    //animalCarer.display(animal)
    animalCarer.display(dog)
    animalCarer.display(puppy)
  }
}

Đoạn code trên hoạt động tốt khi chúng ta comment dòng code sau

//animalCarer.display(animal)

Nếu bỏ comment đoạn code này và thử chạy lại. Chúng ta sẽ gặp lỗi khi biên dịch. Bởi vì chúng ta định nghĩa Upper Bound như sau:

class AnimalCarer{
  def display [T <: Dog](t: T){
    println(t)
  }
}

Ở đây chúng ta định nghĩa T <: Dog điều này nghĩa là hàm display chỉ chấp nhận Object class của Dog hoặc kiểu subclass (ví dụ Puppy) của Dog class.  Đây chính là lý do vì sao khi chúng ta truyền supper class của Dog (Animal), chúng ta sẽ gặp lỗi biên dịch “Type Mismatch”

Scala Lower Bounds

Trong Scala, chúng ta có thể định nghĩa Lower Bound trên Type Parameter như hình bên dưới đây:

Ở đây thì T là một Type Parameter và S là một Type. Bằng việc khái báo Lower Bound T >: S nghĩa là Type Parameter hay T này phải giống với Type của S hoặc super-type của S

Ví dụ

[T >: Ordered[T]]

Ở đây chúng ta đã định nghĩa Lower Bound từ Type Parameter T đến Ordered[T]. Do đó T phải là Ordered hoặc super-type của Ordered.

Tiếp theo hãy cùng xem đoạn code sau đây để hiểu rõ hơn về Lower Bound

class  Animal
class Dog extends Animal
class Puppy extends Animal

class AnimalCarer{
  def display [T >: Puppy](t: T){
    println(t)
  }
}

object ScalaLowerBoundsTest {
  def main(args: Array[String]) {

    val animal = new Animal
    val dog = new Dog
    val puppy = new Puppy

    val animalCarer = new AnimalCarer

    animalCarer.display(animal)
    animalCarer.display(puppy)
    animalCarer.display(dog)
  }
}

Ở đây thì Dog không phải là subtype của Puppy, nhưng đoạn code trên vẫn hoạt động tốt bởi vì Dog là subtype của Animal và chúng ta đã định nghĩa Lower Bound trên Type Parameter T như bên dưới đây

class AnimalCarer{
  def display [T >: Puppy](t: T){
    println(t)
  }
}

Nếu chúng ta bỏ định nghĩa Lower Bound trong class này thì sẽ có một lỗi xảy ra khi biên dịch chương trình

Scala View Bounds

Trong Scala, View Bound thường được sử dụng khi chúng ta muốn sử dụng các chuyển đổi implicit hiện tại tự động.  Chúng ta có thể định nghĩa View Bound trên Type Parameter như hình bên dưới đây:

Trong một vài trường hợp, chúng ta phải sử dụng chuyển đổi ngầm tự động để giải quyết vấn đề câu lệnh. Chúng ta có thể sử dụng View Bound để sử dụng những ngụ ý ngầm này.

Sau đây chúng ta sẽ thử viết một chương trình để so sánh các String với các toán tử quan hệ (như là Int 10 > 12).

class Person[T <% Ordered[T]](val firstName: T, val lastName: T) {
  def greater = if (firstName > lastName) firstName else lastName
}

object ScalaViewBoundsTest {
  def main(args: Array[String]) {
    val p1 = new Person("Rams","Posa")
    val p2 = new Person("Chintu","Charan")

    println(p1.greater)
    println(p2.greater)
  }
}

Kết quả

Rams
Chintu

Nếu chúng ta không sử dụng toán tử View Bound <% thì chúng ta sẽ nhận được thông báo lỗi sau:

error: value > is not a member of type parameter T

 

You May Also Like

About the Author: Nguyen Dinh Thuc

Leave a Reply

Your email address will not be published.