Loại đơn lẻ và ETSR không giải quyết được sự cố. Bản thân tôi cũng đang tìm kiếm một tính năng tương tự ở Scala, nhưng dường như nó thiếu các chú thích tự gõ.
Có những trường hợp chú thích tự nhập như vậy có thể rất hữu ích. Hãy xem xét một ví dụ (được điều chỉnh từ Circular type parameters question example):
// we want a container that can store elements
trait Container[E <: Element[E]] {
def elements: Seq[E]
def add(elem: E): Unit
}
// we want elements be aware of their enclosing container
trait Element[E <: Element[E]] {
def container: Container[E]
}
Giả sử bạn đưa nó vào thư viện. Người tiêu dùng thư viện nên làm như sau:
object PersonContainer extends Container[Person] {
// actual implementation is not important
def elements = Nil
def add(p: Person) = {}
}
class Person extends Element[Person] { // {1}
def container = PersonContainer
}
Đó là tất cả và mọi thứ hoạt động như mong đợi. Điều duy nhất quan tâm là người tiêu dùng thư viện là được cho là để sử dụng thông số loại tự ràng buộc (# 1 trong mã). Nhưng đó không phải là tất cả. Bây giờ giả sử bạn có một số loại mô hình ActiveRecord trong đầu và bạn muốn thêm phương thức save
vào Element
, chỉ ủy quyền cho phương thức add
của vùng chứa đó. Đáng ngạc nhiên, nó không phải là dễ dàng:
trait Element[E <: Element[E]] {
def container: Container[E]
def save() = container.add(this) // won't compile
}
found : Element[E]
required: E
trực giác, chúng ta có một vài lựa chọn ở đây:
- làm
add
phương pháp chấp nhận Element[E]
thay vì E
;
- truyền
this
đến Element[E]
.
Không ai trong số các tùy chọn này thỏa đáng, chỉ vì thực tế là E
là không giống như Element[E]
(triển khai không buộc phải sử dụng các tham số kiểu tự-bound). Cách duy nhất tôi thấy giải quyết vấn đề này là phải có đó tự loại khái niệm trong Scala (chúng ta hãy giả sử chúng ta có nó trong ngôn ngữ yêu thích của chúng tôi):
trait Container[E <: Element] {
def elements: Seq[E]
def add(elem: E): Unit
}
trait Element { // the type parameter would be redundant ...
def save() = container.add(this) // ... and this would be possible, too, ...
def container: Container[this] // ... if only we could do this
}
Nếu trình biên dịch có thể đối xử với this
(hoặc có thể từ khóa khác) , khi nó được sử dụng bên trong dấu ngoặc vuông, là loại thực hiện thực tế (tức là cùng loại với kết quả của obj.getClass
), thì các vấn đề sẽ biến mất.
P.S. Có thể ai đó xem xét đưa công cụ này vào danh sách yêu thích của Scala? Thật không may, tôi không biết, làm thế nào khó để thực hiện logic như vậy kể từ khi có thể có những vấn đề với erasure khét tiếng của JVM.
P.P.S. Hoặc có thể có một số cách khác mà tôi không biết?
Tôi không nghĩ rằng "this.type" là những gì được gọi là ở đây mặc dù. "this.type" là một loại singleton; nó là loại cá thể "này" chỉ. Hãy thử như bạn có thể, phần tử hợp lệ "Danh sách [this.type]" có thể chứa là "this". –
Có, bạn đã đúng. Tôi đã cố nhớ chính xác nó hoạt động như thế nào. – Lachlan