2017-09-11 34 views
7

Nói rằng tôi muốn khai báo một kiểu dữ liệu đại số đơn giản cho các danh sách số nguyên:Trong Kotlin, làm thế nào để bạn khai báo một lớp dữ liệu với các tham số hàm tạo không?

sealed class IntList 
data class Cons(val head: Int, val tail: IntList): IntList() 
data class Nil() : IntList() 

Tuy nhiên, kết quả khai cuối cùng trong một lỗi

lớp dữ liệu phải có ít nhất một tham số nhà xây dựng chính

  1. Tại sao hạn chế này có mặt? Nhìn vào tài liệu, có vẻ như không có lý do kỹ thuật tốt để yêu cầu các nhà xây dựng lớp dữ liệu không phải là vô giá trị.
  2. Có thể thể hiện các nhà xây dựng vô giá trị mà không cần phải viết nhiều mã soạn sẵn không? Nếu tôi thay đổi tuyên bố cuối cùng để một cái gì đó giống như

    sealed class Nil() : IntList() 
    

    sau đó tôi mất việc triển khai miễn hashCode()equals() đi kèm miễn phí với data class tờ khai.

EDIT

Alex Filatov đã đưa ra một giải pháp ngắn đẹp dưới đây. Rõ ràng, bạn không bao giờ cần nhiều hơn một thể hiện của Nil, vì vậy chúng tôi chỉ có thể xác định một đối tượng singleton

object Nil : IntList() 

Tuy nhiên, những gì chúng ta sẽ làm gì nếu danh sách của chúng tôi đã được tham số hóa bởi một tham số kiểu? Đó là, bây giờ hai dòng đầu tiên của định nghĩa của chúng tôi sẽ là

sealed class List<A> 
data class Cons<A>(val head: A, val tail: List<A>): List<A>() 

Chúng ta không thể khai báo một đối tượng đa hình singleton Nil mà xuất phát từ List<A> cho bất kỳ A, vì chúng ta phải cung cấp một loại bê tông cho A tại thời điểm tờ khai. Các giải pháp (lấy từ this post) là tuyên bố A như một tham số kiểu hiệp biến và tuyên bố Nil như một subtype của List<Nothing> như sau:

sealed class List<out A> 
data class Cons<A>(val head: A, val tail: List<A>): List<A>() 
object Nil : List<Nothing>() 

Điều này cho phép chúng tôi viết

val xs: List<Int> = Cons(1, Cons(2, Nil)) 
val ys: List<Char> = Cons('a', Cons('b', Nil)) 
+0

liên quan: https://stackoverflow.com/questions/37873995/how-to-create-empty-constructor-for-data-class-in-kotlin-android Nhưng có vẻ như không phù hợp với hoàn cảnh của bạn. – BakaWaii

+1

Ngoài ra, "_Lưu ý rằng các thuộc tính không được khai báo trong hàm dựng chính không tham gia kiểm tra bình đẳng và tính toán hashcode._" – BakaWaii

+0

@UlrikRasmussen Tại sao bạn cần 'hashCode()' và 'equals()' nếu lớp không nên chứa bất kỳ trường nào? –

Trả lời

10

data class không có dữ liệu không có ý nghĩa. Sử dụng object cho độc thân:

object Nil : IntList() 
+0

Điều này làm việc tốt cho trường hợp sử dụng của tôi, đó là một kiểu dữ liệu đại số đơn giản mà không cần tham số kiểu. Tuy nhiên, làm thế nào tôi sẽ đi về đại diện cho nhà xây dựng nullary cho các loại tham số? Ví dụ, chúng ta hãy khái quát hóa 'danh sách lớp niêm kín ' với hàm tạo đối thủ 'lớp dữ liệu Cons (val h: A, val t: Danh sách ): Danh sách ()'. Tôi không thể khai báo đối tượng đa hình 'đối tượng Nil : Danh sách ()' –

+0

Tôi đã tìm thấy giải pháp và đã cập nhật câu hỏi cho phù hợp –

0
-2

Nếu bạn thực sự muốn tính đồng nhất trong mã nguồn của mình, bạn có thể sử dụng giá trị mặc định cho loại dữ liệu nhỏ nhất có thể.

data class Nil(val _u: Byte = 0) : IntList() 

hoặc

data class Nil(val _u: Nothing? = null) : IntList() 
Các vấn đề liên quan