2017-08-23 22 views
3

錯誤在第二的println之後不可能:智能投給「布爾」是價值做作

智能投地「布爾」是不可能的,因爲「r.isSquare」是,本來是 可變屬性這個時候

fun main(args: Array<String>) { 
    val r: Rectangle = Rectangle(5,5) 
    println(r.isSquare) 
    r.isSquare = true 
    println(r.isSquare) // error but works with println(r.isSquare?:false) 

} 

data class Rectangle(var height: Int, var width: Int){ 
    var isSquare: Boolean? = null 
} 

如果是空的改變,但將打印空像第一的println,爲什麼我要這麼做?

編輯2

感謝您的回答,我現在明白了: 第一的println是

println(message: Any?) 

其次是的println

println(message: Boolean) 

因爲r.isSquare =真正讓編譯器信任isSquare是布爾值而不是布爾值?

EDIT2

這裏是我如何處理,編譯器,以保持信任isSquare是布爾?

fun main(args: Array<String>) { 
    val r: Rectangle = Rectangle(5, 5) 
    println(r.isSquare) 
    r.isSquare = true as Boolean? // if no cast, he will try wrong println signature 
    println(r.isSquare) 
} 

data class Rectangle(var height: Int, var width: Int){ 
    var isSquare: Boolean? = null 
} 
+1

[Smart cast to'Type'的可能重複是不可能的,因爲'變量'是一個可變的屬性,可以在這個時候改變](https://stackoverflow.com/questions/44595529/smart-cast-因爲變量是一個可變的財產,臨) –

回答

3

由於r.isSquare是一個可變的特性,編譯器不就可以了智能施法的非空屬性空校驗後。

您可以使用let

r.isSquare.let { println(it) } 

let讀取r.isSquare值只有一次,它提供了相同的值it拉姆達內。因此,即使在空檢查之後,您也不必使用?!!來訪問布爾值。

Kotlin spec

語言使用大約前檢查空信息,類型(是,是!),安全呼叫運營商和沒有返流 表達來推斷檢查 (?)。關於變量 的其他信息(超出了從初始化程序明確指定或從其初始化程序 其聲明中推斷出)的其他信息,這些信息可能在某些塊或甚至表達式中更具體。然後使用此信息在這些表達式上啓用更廣泛的 操作,並選擇更具體的重載。

fun main(args: Array<String>) { 
    var x : Any 
    x = "" 
    x.toUpperCase() // OK, smart cast to String 
} 

第一println使用該println(message: Any?)

既然你要分配trueisSquare下一個,編譯器試圖智能鑄isSquareBoolean類型,當你嘗試打印。但它不能巧妙投射,因爲該屬性是一種可變類型。

如果刪除線,r.isSquare = true,那麼編譯器不會嘗試智能與Any?作爲參數,將它轉換爲Boolean,並使用println

+0

但是'println'接受一個空值:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/ println.html –

+0

只能爲'Any'允許可空類型。在你的例子中,'println'是以'Boolean'作爲參數的'println'。你可以強制使用'println'作爲'Any?',就像這樣:'println(r.isSquare as Any?)' – Bob

+0

println(r.isSquare作爲布爾值?)使其工作,但有一個警告:「no演員需要「,如果我刪除這個演員,我回去的錯誤..所以,一方面編譯器的作品,但說我不需要這個演員,另一方面我刪除演員,因爲沒有需要,但它不工作了解更多 – Z3nk

0

爲了使其工作,您必須在變量後面添加一個非空聲明的調用(!!)。 r !! isSquare或r.isSquare !!

fun main(args: Array<String>) { 
    val r: Rectangle = Rectangle(5,5) 
    println(r.isSquare) 
    r.isSquare = true println(r.!! isSquare) 
} 

data class Rectangle(var height: Int, var width: Int) { 
    var isSquare: Boolean? = null 
} 
+0

你不回答這個問題,我知道我必須做一個非null斷言的電話或像我寫我的評論println(r.isSquare?:false) 我的問題是爲什麼我必須在第二個println中執行此操作,而不是第一個? 此外,println可以打印空值(只有isSquare可以在我的代碼中爲空,而不是r) – Z3nk

0

由於isSquare是一個可變屬性(var)。這意味着你在哪些行寫了一個值然後你讀取它的行之間,另一個線程可以修改它,並因此得到一個NPE。

r.isSquare = true 
//Another thread set r.isSquare = null 
println(r.isSquare) // you get a null pointer exception 

你必須在每次可空瓦爾工作時間檢查屬性爲空。

0

因爲Android中的println()函數不支持布爾型?和布爾型? kotlin的可變屬性不能由Kotlin的智能轉換自動解包。

試試字符串?還是Int?或者任何具有可變和可空屬性的類型都會發生相同的事情。