2015-11-14 25 views
10

Tôi không thể hiểu được những mảnh sau của tài liệu Kotlin:Tại sao trình biên dịch Kotlin yêu cầu khởi tạo rõ ràng thuộc tính var?

The initializer, getter and setter are optional. Property type is optional 
if it can be inferred from the initializer or from the base class member being overridden. 

Examples: 
var allByDefault: Int? // error: explicit initializer required, default 
getter and setter implied 

Lời giải thích duy nhất của lý do tại sao các trình biên dịch đòi hỏi initializer rõ ràng ở đây (ít nhất là lời giải thích duy nhất tôi có thể đưa ra) là Kotlin không có giá trị mặc định của thuộc tính. Đúng không? Nếu vậy, tại sao? Nói cách khác: sự khác biệt giữa các thuộc tính Kotlin và các trường Java (có các giá trị mặc định) nào không cho phép chúng ta có các giá trị mặc định của các thuộc tính?

Trả lời

7

Điều đó đơn giản: trong các giá trị mặc định Java là 0 (số không) và null. Nhưng ở Kotlin, hầu hết các giá trị đều không có giá trị, vì vậy bạn không thể khởi tạo chúng với null. Đối với các giá trị nguyên thuỷ, có thể có một chiến lược mặc định khởi tạo với số không, nhưng nó không được thực hiện để nhất quán. Nhưng trong các mảng nguyên thủy, giá trị mặc định bằng 0.

Nếu bạn thực sự cần ngữ nghĩa khởi tạo đó, hãy xem lateinit thuộc tính: https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties.

Cơ chế đó về cơ bản cho phép bắt đầu một trường bằng null, nhưng sau đó giải phóng bạn khỏi các xác nhận không có giá trị.

BỔ SUNG

Trên thực tế Kotlin là rất minh về khởi tạo. Ví dụ hoạt động:

val x: Int 

if(something) 
    x = 1 
else 
    x = 2 

println(x) 

Đây kotlinc thể proove rằng x đang được khởi tạo trước nó đang được sử dụng, vì vậy mã là OK

+1

"Nhưng trong Kotlin hầu hết các giá trị không nullable, vì vậy bạn không thể khởi tạo chúng với null" - Tôi được hỏi cụ thể về thuộc tính được khai báo như vậy: 'var allBeDefaut: Int?'.Rõ ràng, đây là biến nullable và nó có thể được khởi tạo với 'null' theo mặc định, trái ngược với, giả sử' var someVar: Int'. – aga

+0

@aga Nhưng sự nhất quán là rất quan trọng. Bên cạnh việc khởi tạo mặc định là hơi gián tiếp/vô hình, bạn cũng nên tránh. Hầu như bất kỳ trường hợp sử dụng cho rằng có một giải pháp thanh lịch hơn – voddan

+0

Và tôi không bao giờ nhìn thấy một sử dụng tốt cho initialisation mặc định, trong bất kỳ ngôn ngữ mà tôi đã làm việc với – voddan

1

Kotlin không làm gì cả ngầm. Nó không chuyển đổi các kiểu số mà không có lệnh cụ thể của bạn, cũng như không đặt giá trị mặc định hoặc khởi tạo mà không có nó rõ ràng. Nó là một lựa chọn thiết kế để loại bỏ các lỗi phổ biến được tìm thấy trong các chương trình Java điển hình. Nó không phải là rõ ràng cho trình biên dịch nếu bạn quên khởi tạo nó hoặc nếu bạn có nghĩa là cho một giá trị mặc định sẽ được sử dụng. Vì nó không rõ ràng, nó là xấu. Và do đó có thể dẫn đến lỗi.

Các lựa chọn thiết kế của Kotlin giúp loại bỏ lỗi do mã trong đó trình biên dịch không thể giúp xác định xem có lỗi hay không. Đó là triết học và nhất quán trong ngôn ngữ.

Kotlin yêu cầu khởi tạo trước khi sử dụng. Đối với các thành viên có nghĩa là bởi các nhà xây dựng thời gian và khởi tạo được hoàn thành, nó phải có một giá trị. lateinit sửa đổi trên var cho phép điều này được bỏ qua tại thời gian biên dịch mặc dù lúc chạy kiểm tra được thực hiện khi bạn truy cập biến. Đối với các biến cục bộ, bất kỳ nhánh mã nào đều phải khởi tạo giá trị trước khi truy cập. Ví dụ:

fun stateFromAbbreviation(abbreviation: String?): String { 
    val state: String 

    if (abbreviation == null) { 
     state = DEFAULT_STATE 
    } 
    else { 
     state = stateMap.get(abbreviation) ?: throw IllegalStateException("Invalid state abbreviation $abbreviation") 
    } 

    return state 
} 

Tại đây, biến cục bộ có thể được khởi tạo trong câu lệnh if giả định tất cả các chi nhánh khởi tạo giá trị. Nhưng thực sự, mã này sẽ được nhiều thành ngữ sử dụng if như một biểu hiện, chẳng hạn như:

fun stateFromAbbreviation(abbreviation: String?): String { 
    return if (abbreviation == null) { 
     DEFAULT_STATE 
    } 
    else { 
     stateMap.get(abbreviation) ?: throw IllegalStateException("Invalid state abbreviation $abbreviation") 
    } 
} 
Các vấn đề liên quan