Trong Scala, chúng tôi có thể sử dụng ít nhất hai phương pháp để trang bị thêm các loại hiện có hoặc mới. Giả sử chúng ta muốn thể hiện rằng một cái gì đó có thể được định lượng bằng cách sử dụng một Int
. Chúng ta có thể xác định đặc điểm sau.
Chuyển đổi ngầm định
trait Quantifiable{ def quantify: Int }
Và sau đó chúng ta có thể sử dụng các chuyển đổi ngầm định để định lượng, ví dụ: Chuỗi và Danh sách.
implicit def string2quant(s: String) = new Quantifiable{
def quantify = s.size
}
implicit def list2quantifiable[A](l: List[A]) = new Quantifiable{
val quantify = l.size
}
Sau khi nhập chúng, chúng ta có thể gọi phương thức quantify
trên chuỗi và danh sách. Lưu ý rằng danh sách có thể định lượng lưu trữ độ dài của nó, do đó, nó tránh việc duyệt danh sách tốn kém trong các lần gọi tiếp theo quantify
.
Loại lớp
Một giải pháp thay thế là xác định một "nhân chứng" Quantified[A]
nói rằng, một số loại A
có thể được định lượng.
trait Quantified[A] { def quantify(a: A): Int }
Sau đó, chúng tôi cung cấp các thể hiện của lớp loại này cho String
và List
ở đâu đó.
implicit val stringQuantifiable = new Quantified[String] {
def quantify(s: String) = s.size
}
Và nếu sau đó chúng ta viết một phương thức cần định lượng các đối số của nó, chúng ta sẽ viết:
def sumQuantities[A](as: List[A])(implicit ev: Quantified[A]) =
as.map(ev.quantify).sum
Hoặc sử dụng cú pháp liên kết ngữ cảnh:
def sumQuantities[A: Quantified](as: List[A]) =
as.map(implicitly[Quantified[A]].quantify).sum
Nhưng khi nào thì sử dụng phương pháp nào?
Bây giờ đến câu hỏi. Làm thế nào tôi có thể quyết định giữa hai khái niệm đó?
Những gì tôi đã nhận thấy cho đến nay.
loại lớp
- các lớp kiểu cho phép cú pháp ràng buộc ngữ cảnh đẹp
- với các lớp kiểu, tôi không tạo đối tượng trình bao bọc mới mỗi lần sử dụng
- cú pháp ràng buộc ngữ cảnh không hoạt động nữa nếu lớp kiểu có nhiều tham số kiểu; Hãy tưởng tượng tôi muốn định lượng mọi thứ không chỉ với số nguyên mà với các giá trị của một số loại tổng quát
T
. Tôi muốn tạo một loại lớpQuantified[A,T]
chuyển đổi ngầm
- vì tôi tạo một đối tượng mới, tôi có thể lưu các giá trị vào bộ nhớ cache ở đó hoặc tính toán một biểu diễn tốt hơn; nhưng tôi có nên tránh điều này không, vì nó có thể xảy ra vài lần và một chuyển đổi rõ ràng có thể chỉ được gọi một lần?
Những gì tôi mong đợi từ một câu trả lời
Trình bày một (hoặc nhiều) trường hợp sử dụng mà sự khác biệt giữa cả hai khái niệm đều quan trọng và giải thích lý do tại sao tôi thích cái này hơn cái kia. Ngoài ra, giải thích bản chất của hai khái niệm và mối quan hệ của chúng với nhau sẽ rất tốt, ngay cả khi không có ví dụ.