2011-12-22 12 views
27

Việc thiếu các generics được sửa đổi trong Scala là thứ làm tôi khó hiểu nhất về ngôn ngữ, vì không thể triển khai simple things mà không cần sử dụng các cấu trúc phức tạp.Generics generics trong Scala 2.10

Cả Kotlin và Ceylon đều hỗ trợ các generics được cải tiến để chắc chắn nó có thể thực hiện trên đỉnh JVM. Trong số past người ta nói rằng Scala không thể hỗ trợ họ mà không có sự thay đổi trong JVM, nhưng bây giờ Scala 2.10 là rumored để có sự hỗ trợ hạn chế cho việc tái hợp. Vì vậy, câu hỏi của tôi là:

  • Điều gì chúng ta có thể mong đợi để sửa đổi trong Scala 2.10, tôi có thể triển khai generic trait multiple times? Chỉ giới hạn là bao nhiêu?
  • Nếu việc sửa đổi Scala 2.10 trở nên hạn chế hơn KotlinCeylon. Tại sao vậy ?
+0

Tôi đã cố gắng cập nhật câu hỏi để bây giờ hy vọng sẽ đơn giản hơn để trả lời r (như trong Có/Không, bạn không thể thực hiện một đặc điểm chung trong nhiều lần trong Scala 2.10 vì việc sửa đổi kiểu sẽ yêu cầu mang tên trong các lớp được tạo ra, làm cho chúng phức tạp khi sử dụng trong Java. Hoặc bất kể câu trả lời có thể là gì. –

+4

Odersky * cho biết * việc chỉnh sửa là 2,10, vì vậy nó không chỉ là tin đồn. – Malvolio

+2

Bạn có nghĩa là Kotlin không tồn tại và Ceylon-that-was-just-release-without-reification cho thấy rằng các generics đã được tái hợp là có thể? Nó hoạt động như thế nào? –

Trả lời

30

Đối số của bạn không hoàn thiện. Kotlin đã chưa được công bố *, và Ceylon chỉ có phiên bản đầu tiên của nó được phát hành, và tôi sẽ báo giá một trong những điều đó là mất tích từ their announcement:

  • reified generics

Như vậy, cho tôi xin lỗi, nhưng thực hiện chứng minh điều đó là có thể? Trong thực tế, tôi đã không nhìn nhiều vào những gì Kotlin đang hứa hẹn, nhưng những gì Ceylon là đầy hứa hẹn chỉ là những gì biểu hiện đã cung cấp, nhưng một cách minh bạch.

Nhưng chúng ta hãy xem xét các vấn đề bạn mô tả trong câu hỏi của bạn:

trait Handles[E <: Event] { 
    def handle(event: E) 
} 

Vì vậy, trước hết, JVM không cung cấp bất kỳ cách nào xác định các tham số gõ vào giao diện hoặc các lớp học, vì vậy Ekhông thể được được JVM kiểm tra. Bạn có thể, tuy nhiên, lưu trữ thông tin về những gì E là viết tắt của từng đối tượng mà thực hiện Handles, giống như bạn có thể viết những dòng này trong Scala:

abstract class Handles[E <: Event : Manifest] { 
    def handle(event: E) 
} 

Tiếp theo, chúng ta hãy xem các phương pháp handle. Một lần nữa, JVM không cung cấp cách nào để sử dụng các tham số kiểu trong một định nghĩa phương thức. Cách duy nhất để thực hiện điều đó là để có handle chấp nhận Object làm thông số: nghĩa là xóa loại.

Và đây là giao dịch: để thực hiện handle có thể gọi từ Java, nó phải được xóa. Và, nếu nó là loại bị xóa, thì nó phụ thuộc vào giới hạn được mô tả trong câu hỏi của bạn. Cách duy nhất để vượt qua đó là giảm khả năng tương thích Java (mà, nhân tiện, cũng không có trong bản phát hành đầu tiên của Ceylon).

Có, Scala sẽ có sự cải tổ (một số loại) vào ngày 2.10, theo Martin Odersky. Nhưng bất cứ điều gì nó cung cấp (và tôi cá cược về việc sử dụng các biểu hiện minh bạch hơn để khẳng định sự bình đẳng kiểu), giới hạn cụ thể này là nội tại đối với JVM và không thể khắc phục mà không làm mất tích hợp Java.

(*) Kotlin có bản trình diễn ngay bây giờ và việc cải tổ lại - cho đến nay - chỉ là một đường cú pháp để gói các tệp kê khai và kiểm tra instanceOf. Nó vẫn phải chịu mọi hạn chế giống như Scala.

+1

Tôi giả định rằng kể từ khi các thông số kỹ thuật đề cập đến sự cải cách (fx. Http://goo.gl/jMvzG) rằng các tác giả đã thực sự tìm thấy một cách để làm điều đó. Nếu không thì bạn là nguyên nhân hoàn toàn chính xác. Câu hỏi của tôi là nhiều hơn về bản chất của Generics trong 2,10 và tại sao nó là kotlin và ceylon có thể giải quyết vấn đề này và Scala không thể (giả sử họ có thể). –

+4

@Lars: Không, không có cách nào để thực hiện các generic generified đúng trên JVM, mà không tạo ra một sự trừu tượng hoàn toàn mới giữa JVM, class-files, bytecode và ngôn ngữ. Mặc dù thực tế là hai ngôn ngữ mới yêu cầu hỗ trợ generics được đổi mới, những ngôn ngữ đó đã không chuyển giao gì cho đến ngày nay, ngoại trừ một số thử nghiệm instanceOf được làm rõ. – soc

+1

Gosu hỗ trợ Generics thống nhất, và mặc dù Kotlin và Ceylon không có phát hành ra rằng hỗ trợ họ, không có nghi ngờ trong tâm trí của tôi họ sẽ là tốt. Có nói rằng, tôi nghĩ rằng việc thêm các generics đã được cải tiến trong Scala là một sai lầm sẽ gây ra một số điện thoại trên ngôn ngữ, trong khi cần truy cập thông tin chung là khá hiếm và thường gặp đầy đủ với các biểu hiện. Liên kết Gosu: http://gosu-lang.org/doc/Gosu%20Reference%20Guide/wwhelp/wwhimpl/common/html/wwhelp.htm#context=gosu&file=intro.03.09.html –

3

Theo những gì Andrey Breslav đang nói về this loại trang Kotlin không đã reified:

"Yes, type parameters are not available in class objects"

+3

Các loại đã được loại bỏ sẽ bị loại bỏ trong Kotlin: "Các generics được cải tiến chỉ có thể được thực hiện cho JVM với chi phí hiệu năng lớn và chúng tôi đã quyết định hủy bỏ tính năng này." Xem http://devnet.jetbrains.com/message/5479326#5479326 – OlliP

+2

Trong khi đó, bản phát hành chính thức tiếp theo của Ceylon sẽ bao gồm các đại tướng đã được chỉnh sửa http://www.ceylon-lang.org/blog/2013/02/21/reification -finally/ – Chochos

+1

@Ollip câu trả lời của bạn nên được cập nhật, Kotlin không có generics reified cho các chức năng nội tuyến được sử dụng nhiều và giải quyết các trường hợp phổ biến nhất. Câu trả lời của bạn giờ đây đã gây hiểu lầm cho Kotlin hiện tại. –

7

Kotlin đã reified Generics cho các thông số loại chức năng nội tuyến, như ghi nhận ở đây: https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters. Điều này đã tồn tại trong Kotlin một thời gian, chúng được sử dụng bởi nhiều thư viện đã có trong hệ sinh thái Kotlin. Các câu trả lời khác ở đây đã lỗi thời khi đề cập đến Kotlin. Kotlin đã được phát hành dưới dạng 1.0 kể từ tháng Hai, 2016.

Ví dụ về Generics reified trong Kotlin, nổi tiếng TypeReference ở Jackson, khi được sử dụng trong Jackson Kotlin module sử dụng mã này:

public inline fun <reified T: Any> ObjectMapper.readValue(jp: JsonParser): T 
    = readValue(jp, object: TypeReference<T>() {}) 

Và cùng một điều từ thư viện Injekt của Kotlin:

public inline fun <reified T: Any> fullType(): FullTypeReference<T> 
    = object:FullTypeReference<T>(){} 

public inline fun <reified T : Any> injectLazy(): Lazy<T> { 
    return lazy { Injekt.get(fullType<T>()) } 
}