2017-12-19 244 views
12

ab null bir değişken var. Ona null atadıktan sonra toUpperCase numaralı telefonu güvenli arama operatörü ile ararsam, kotlin hata verir.Kotlin güvenli aramasında aşırı yük çözünürlüğü hatası alıyorum

fun main(args: Array<String>){ 
    var ab:String? = "hello" 
    ab = null 
    println(ab?.toUpperCase()) 
} 

Error:(6, 16)
Overload resolution ambiguity:
@InlineOnly public inline fun Char.toUpperCase(): Char defined in kotlin.text
@InlineOnly public inline fun String.toUpperCase(): String defined in kotlin.text

Ne oluyor burada?

cevap

2

Emin değilim, ancak bu akıllı döküm nedeniyle bir hata gibi görünüyor (Nothing?, her nullable türün alt türü için). Bu seferki çalışır:

fun main(args: Array<String>) { 
    var ab: String? = "hello" 
    ab = makeNull() 
    println(ab?.toUpperCase()) 
} 

fun makeNull(): String? = null 

tek fark: derleyici sizin örnekte hataya neden görünmektedir ki, doğrudan null atama bilmiyor. Ama yine de, muhtemelen senin de çalışmalısın.

2

Gerçekten bir hata gibi görünüyor. String?, bir şekilde null atanırken kaybolur, bu nedenle derleyiciye açıkça bir String? ile uğraşması gerektiğini bildirmeniz gerekir.

fun main(args: Array<String>){ 
    var ab: String? = "hello" 
    ab = null 
    println((ab as String?)?.toUpperCase()) // explicit cast 

    // ...or 

    println(ab?.let { it.toUpperCase() }) // use let 
} 
1

Bu KOTLIN kullandığı smart casts nedeniyle olduğuna inanıyoruz. Başka bir deyişle, Kotlin bu kod satırdan sonra sonucuna yapabiliyor: - Ben sadece aralığında bahsediyorum değişken ab tipi basitçe null

ab = null 

olduğunu (bu KOTLIN kullanabileceğiniz gerçek türü değil izin verilen değerler), String? (başka bir deyişle, yokturab hiçbir String içerebilir).

toUpperString() uzantısı işlevinin yalnızca Char ve String (Char? Veya String? Değil) için tanımlandığını dikkate alarak, aralarında seçim yapmanın bir yolu yoktur.

Bu davranıştan kaçınmak için diğer kişiler tarafından önerilen yanıtlara bakın (örneğin, String'e açık bir şekilde casting?), Ancak bu kesinlikle benim için bir hatadan ziyade bir özellik (ve oldukça kullanışlı olanı) gibi görünüyor. Bu doc about smart-casts belirtildiği gibi

+1

"Değişken ab türü basitçe boş" null bir tür değil! –

+0

"toUpperString() uzantısı işlevinin yalnızca Char ve String (Char? Veya String? Değil) için tanımlandığını dikkate alarak, aralarında seçim yapmanın bir yolu yoktur." güvenli arama operatörü kullanılır ve bu nedenle, null olması durumunda, toUpperString() asla ab olarak çağrılmaz. –

+0

"... bir String içermeyen bir yol yoktur)" null atamadan sonra ne ab = "merhaba2" a atarsam. aniden * bir tekrar * içeren bir yol * var. –

5

:

x = y makes x of the type of y after the assignment

hat ab = null muhtemelen akıllı atmalarını abNothing? için. ab is Nothing?'u kontrol ederseniz, gerçekten true. Nothing? yana

var ab: String? = "hello" 
ab = null 
println(ab?.toUpperCase()) 
println(ab is Nothing?) // true 

(Char? ve String? dahil) her türlü alt tipi olan, bu Overload resolution ambiguity hatası alıyorum açıklıyor. Bu hata için çözüm, his answer numaralı Willi Mentzel'in ab no'lu dökümdetürünü toUpperCase() numaralı telefonu aramadan önce türetmesiyle açıklayacaktır.

//interface 
interface A {} 
interface B {} 

//extension function 
fun A.x() = 0 
fun B.x() = 0 

//implementing class 
class C : A, B {} 

C().x() //Overload resolution ambiguity 
(C() as A).x() //OK. Call A.x() 
(C() as B).x() //OK. Call B.x() 
+0

Bekleyin, 'ab' zaten ilk satırda bir NULL Dize olarak tanımlanmadı mı? Öyleyse neden String'e atılmalı? gerekli olmak? – donfuxx

+0

@donfuxx 'ab' türünün 'Nothing?' Ve 'Nothing?' Türlerinin her ikisi de 'String?' Ve' Char? 'Türlerinin alt tipi olduğu için. Aynı zamanda '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'ile ifade edilen bir' 'toUpperCase()' uzantısı fonksiyonu vardır Yani derleyiciye, uzatma işlevini alıcı olarak "String" ile çağırmak istediğimizi söylemeliyiz. – BakaWaii

+0

Kutsal inek, sadece soru kodunun hata ayıklayıcısında adım attı ve “ab Nothing?”, Doğru olarak değerlendirildi. Yani "akıllı" oyuncu oldu sanırım .. ama muhtemelen "aptal" cast daha iyi bir isim olurdu ;-) Ben diğer cevaplar gibi bir kotlin hata olarak görmek tercih, ama yine de bu cevap yardımcı analiz beri başparmak yukarıya: – donfuxx

1

Ben senin fonksiyonunu Decompiled ben de işte:


Açıklamalar: Bir sınıf iki arabirimleri uygulayan ve her iki arayüz aynı imzanın uzantısı işlevini varken Bu tür bir hata meydana gelecektir andan sonra ab = null yapmak derleyici, ab'un her oluşunda null (ACONST_NULL)'u yerleştirir. Daha sonra null'un türü yok. toUpperCase() alıcısının türünü çıkaramazsınız.

public final void main(@NotNull String[] args) { 
    Intrinsics.checkParameterIsNotNull(args, "args"); 
    String ab = "hello"; 
    ab = (String)null; 
    Object var3 = null; 
    System.out.println(var3); 
} 

Bu KOTLIN ekibi tarafından çözülmesi gereken bir sorun olarak görünmektedir:

Bu KOTLIN bayt kodundan üretilen java eşdeğer kodudur.

+0

Not: Kodu derlemek/kodunu derlemek için 'toUpperCase' yerine' toInt 'kullandım – crgarridos