2016-02-16 25 views
11

Tôi đã gặp sự cố trong ứng dụng Android của mình bằng Kotlin và RxJava. Nó được trình bày dưới đây.Kotlin RxJava Nullable Bug

import rx.Observable 

data class TestUser(val name: String) 

fun getTestUser(): Observable<TestUser> { 
    return Observable.just(TestUser("Brian")).flatMap { getUser() } // this compiles 
} 

fun getTestUser2(): Observable<TestUser> { 
    val observable = Observable.just(TestUser("Brian")).flatMap { getUser() } 
    return observable // this does not compile 
} 

fun getUser(): Observable<TestUser?> { 
    return Observable.just(null) 
} 

Trong getTestUser2, trình biên dịch suy luận kiểu trả về thức như Observable<TestUser?> và không biên dịch. Tuy nhiên, trong getTestUser mã không biên dịch, và khi nó chạy, bất kỳ thuê bao để mà quan sát được có thể được in cho một bất ngờ khi TestUser trở lại null.

Tôi đoán nó là cái gì để làm với đi lại giữa Kotlin và Java. Nhưng, thực tế là trình biên dịch có thể thấy sự khác biệt trong getTestUser2 làm cho tôi nghĩ rằng điều này có thể khắc phục được.

Chỉnh sửa

Đây là phiên bản cuối cùng Kotlin 1.0 phát hành ngày hôm qua (ngày 15 tháng 2 năm 2016).

+0

Tôi nghĩ rằng, đây là theo dõi vấn đề họ đang sử dụng: https://youtrack.jetbrains.com/issues/KT . Bạn có nhiều khả năng nhận được xác nhận/giải thích từ những người tạo ngôn ngữ, nếu bạn tạo báo cáo lỗi –

+2

Nhóm xác nhận đó là một lỗi. Vấn đề: https://youtrack.jetbrains.com/issue/KT-11108 – voddan

Trả lời

10

Chữ ký của flatMap chức năng như sau khi được sử dụng trong Kotlin:

public final fun <R: Any!, T: Any!> 
    Observable<T>.flatMap(
     func: ((T) -> Observable<out R!>!)! 
    ) : Observable<R!>! 

Từ các tài liệu:

Bất kỳ tài liệu tham khảo trong Java có thể null, mà làm cho yêu cầu Kotlin của nghiêm ngặt an toàn không thực tế đối với các đối tượng đến từ Java. Các loại các khai báo Java được xử lý đặc biệt trong Kotlin và được gọi là các loại nền tảng . Null-tờ séc đều thoải mái với nhiều loại như vậy, để an toàn đảm bảo cho họ cũng giống như trong Java

T! có nghĩa là “T hoặc T?

này phương tiện trình biên dịch Kotlin có thể coi kiểu trả về của hàm flatMapObservable<TestUser> hoặc Observable<TestUser?> hoặc thậm chí Observable<TestUser>?. Phần thư giãn nói nhiều như, "chúng tôi không muốn làm phiền bạn với những loại không rõ, bạn có thể biết rõ hơn".

Kể từ khi kiểu trả được đưa ra một cách rõ ràng trong getTestUser(), nó sử dụng đầu tiên. Kể từ khi loại observablekhông được một cách rõ ràng, nó suy luận nó để Observable<TestUser?>, dựa trên getUser() chức năng.


Như @voddan nhận xét, có một vấn đề mở thảo luận về vấn đề này: https://youtrack.jetbrains.com/issue/KT-11108

+0

Đã chấp nhận điều này. Cũng nghiên cứu và trình bày. Điều đó có ý nghĩa. Tôi có thể sẽ bắt đầu rõ ràng hơn bằng cách gán giá trị trước khi trả về giá trị như trong ví dụ thứ 2.Tôi muốn tất cả các loại an toàn tôi có thể nhận được. – bclymer

+1

Thật kỳ lạ. Việc chuyển nhượng mà không có khai báo kiểu không nên thay đổi một điều gì đó. – voddan

+2

Nhóm xác nhận đó là một lỗi. Vấn đề: https://youtrack.jetbrains.com/issue/KT-11108 – voddan