Smartcast ist unmöglich, weil propery einen offenen oder benutzerdefinierten Getter hat

8

Ich lerne Kotlin. Mein Code ist wie folgt:

%Vor%

attachRouter() Methode:

%Vor%

Wie in der Dokumentation beschrieben, wird Kotlin automatisch nach der Überprüfung mit dem is-Operator in den Typ umgewandelt. Also habe ich erwartet, dass es funktionieren würde. Aber stattdessen stört mich ein Kompilierungsfehler, der sagt:

Smartcast to ScreenRouter ist unmöglich, weil activity eine Property ist, die einen offenen oder benutzerdefinierten Getter hat.

Ich dachte, vielleicht ist der Fehler, weil die Aktivität nullfähig sein kann, also habe ich es versucht:

%Vor%

Aber es hat nicht funktioniert und die Kompilierung ist mit demselben Fehler fehlgeschlagen.

Der folgende Code funktioniert jedoch einwandfrei:

%Vor%

Es ist in Ordnung, aber der obige Fehler scheint nichts darüber zu erklären, warum Smartcast fehlschlägt. Ich bin kein Kotlin-Experte, ich bin nur ein Anfänger, der Kotlin lernt. Ich habe nirgendwo eine Dokumentation gefunden. Diese Art von Fehlerbeschreibungen machen Kotlin schrecklich zu lernen. Kann jemand das einfach erklären?

    
Krupal Shah 11.12.2016, 12:44
quelle

1 Antwort

14

Der entscheidende Punkt hierbei ist, dass eine open -Eigenschaft oder eine Eigenschaft mit einem benutzerdefinierten Getter bei aufeinanderfolgenden Aufrufen nicht garantiert denselben Wert zurückgibt.

Daher kann der Compiler nicht sicher sein, dass nach dem Überprüfen des von der Eigenschaft empfangenen Werts sicher davon ausgegangen werden kann, dass er dasselbe Objekt oder sogar ein Objekt desselben Typs zurückgibt, wenn er erneut aufgerufen wird.

Beispiel (ziemlich vereinfacht und synthetisch):

%Vor%

Dieser Code wird nicht kompiliert, weil printArrayList() ein ArrayList erwartet und b.value ist open - das ist, was Sie in Ihrem Code bekommen. Jetzt stellen wir eine abgeleitete Klasse zusammen, die zeigt, was schiefgehen könnte:

%Vor%

Hier ist es ziemlich klar, dass, wenn eine Eigenschaft open ist, sie so überschrieben werden kann, dass aufeinander folgende Aufrufe unterschiedliche Werte zurückgeben. Im Beispiel mit printArrayList() gibt es zwei solche Aufrufe. Deshalb wäre die intelligente Besetzung nicht sicher. Dasselbe gilt für Eigenschaften mit benutzerdefinierten Gettern.

Ihr Beispiel, das einen as -cast im Block if ausgeführt hat, funktionierte, weil der Cast fehlschlagen und einen ClassCastException ausgeben würde, wenn die Eigenschaft beim zweiten Aufruf einen anderen Wert eines nicht kompatiblen Typs zurückgegeben hätte Dies würde die Sicherheit des Typs bewahren.

Und im Gegensatz dazu, wenn eine val -Eigenschaft nicht open ist und einen Standard-Getter hat, der einfach den Wert von unterstützendes Feld (was in diesem Fall final ist), kann der Compiler sicher einen Smart Cast durchführen: Wenn Sie den Wert der Eigenschaft mehrmals erhalten, ist es sicher, dass er derselbe ist .

Alternativ können Sie den Wert auch einmal abrufen, in einer lokalen Variablen speichern und mehrmals verwenden, anstatt die Eigenschaft erneut zu verwenden:

%Vor%

Nun, unabhängig davon, ob eine Eigenschaft open ist, gibt es nur einen Aufruf an den Getter, und der Code arbeitet dann mit dem Wert, den der Aufruf zurückgegeben hat. Da es sich nicht ändern kann, ist der Smartcast hier möglich.

    
hotkey 11.12.2016, 13:07
quelle

Tags und Links