{"id":127683,"date":"2021-03-09T11:34:27","date_gmt":"2021-03-09T10:34:27","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=127683"},"modified":"2021-03-25T12:11:21","modified_gmt":"2021-03-25T11:11:21","slug":"vorschau-der-neuen-sprachmerkmale-in-kotlin-1-4-30","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/de\/kotlin\/2021\/03\/vorschau-der-neuen-sprachmerkmale-in-kotlin-1-4-30\/","title":{"rendered":"Vorschau der neuen Sprachmerkmale in Kotlin 1.4.30"},"content":{"rendered":"<p>Wir planen, in Kotlin 1.5 neue Sprachmerkmale hinzuzuf\u00fcgen, und Sie k\u00f6nnen diese bereits in Kotlin 1.4.30 ausprobieren:<\/p>\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/02\/new-language-features-preview-in-kotlin-1-4-30\/#inline-value-classes-stabilization\">Stabilisierung von Inline-Wertklassen<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/02\/new-language-features-preview-in-kotlin-1-4-30\/#jvm-records\">Experimentelle Unterst\u00fctzung f\u00fcr JVM-Records<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/02\/new-language-features-preview-in-kotlin-1-4-30\/#sealed-interfaces\">Experimentelle Unterst\u00fctzung f\u00fcr Sealed-Interfaces und weitere Verbesserungen f\u00fcr Sealed-Klassen<\/a><\/li>\n<\/ul>\n<p>Um diese neuen Funktionen auszuprobieren, m\u00fcssen Sie die <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/02\/new-language-features-preview-in-kotlin-1-4-30\/#how-to-try\">Sprachversion 1.5 angeben<\/a>.<\/p>\n<p>Der neue <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2020\/10\/new-release-cadence-for-kotlin-and-the-intellij-kotlin-plugin\/\">Releasezyklus<\/a> sorgt daf\u00fcr, dass Kotlin 1.5 erst in ein paar Monaten ver\u00f6ffentlicht wird, aber die neuen Funktionen sind bereits in 1.4.30 als Vorschau verf\u00fcgbar. Ihr fr\u00fchzeitiges Feedback ist f\u00fcr uns sehr wichtig, also probieren Sie diese neuen Funktionen bitte jetzt aus!<\/p>\n<p><a href=\"https:\/\/youtrack.jetbrains.com\/issues?q=tag:%20Language\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/02\/Kotlin-1.4.30-new-lang-features-banner_2-02.png\" alt=\"\" \/><\/a><\/p>\n<h2>Stabilisierung von Inline-Wertklassen<\/h2>\n<p><a name = \"inline-value-classes-stabilization\"><\/a><\/p>\n<p><a href=\"https:\/\/kotlinlang.org\/docs\/reference\/inline-classes.html\" target=\"_blank\" rel=\"noopener\">Inline-Klassen<\/a> sind seit Kotlin 1.3 in der <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/evolution\/components-stability.html#stability-levels-explained\" target=\"_blank\" rel=\"noopener\">Alphaphase<\/a> verf\u00fcgbar, und in 1.4.30 werden sie in die <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/evolution\/components-stability.html#stability-levels-explained\" target=\"_blank\" rel=\"noopener\">Betaphase<\/a> bef\u00f6rdert.<\/p>\n<p>Kotlin 1.5 stabilisiert das Konzept der Inline-Klassen, macht es aber zu einem Teil einer allgemeineren Funktion, den <em>Value-Klassen<\/em>, die wir sp\u00e4ter in diesem Beitrag beschreiben werden.<\/p>\n<p>Wir beginnen mit einer Auffrischung, wie Inline-Klassen funktionieren. Wenn Sie mit Inline-Klassen bereits vertraut sind, k\u00f6nnen Sie diesen Abschnitt \u00fcberspringen und direkt zu den <a href=\"#jvm-name-support\">neuen \u00c4nderungen<\/a> \u00fcbergehen.<\/p>\n<p>Zur Erinnerung, eine Inline-Klasse eliminiert einen Wrapper um einen Wert:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\ninline class Color(val rgb: Int)\n<\/pre>\n<p>Eine Inline-Klasse kann sowohl ein Wrapper f\u00fcr einen primitiven Typ als auch f\u00fcr einen beliebigen Referenztyp, wie <code>String<\/code>, sein.<\/p>\n<p>Der Compiler ersetzt Inline-Klasseninstanzen (in unserem Beispiel die <code>Color<\/code>-Instanz) im Bytecode durch den zugrunde liegenden Typ (<code>Int<\/code>), wenn dies m\u00f6glich ist:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\nfun changeBackground(color: Color) \nval blue = Color(255)\nchangeBackground(blue)\n<\/pre>\n<p>Im Hintergrund erzeugt der Compiler die Funktion <code>changeBackground<\/code> mit einem besch\u00e4digten Namen, der <code>Int<\/code> als Parameter nimmt, und er \u00fcbergibt die Konstante <code>255<\/code> direkt, ohne einen Wrapper an der Aufrufstelle zu erzeugen:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\nfun changeBackground-euwHqFQ(color: Int) \nchangeBackground-euwHqFQ(255) \/\/ Es wird kein zus\u00e4tzliches Objekt zugeordnet! \n<\/pre>\n<p>Der Name wird besch\u00e4digt, um die nahtlose \u00dcberladung von Funktionen zu erm\u00f6glichen, die Instanzen verschiedener Inline-Klassen annehmen, und um versehentliche Aufrufe aus dem Java-Code zu verhindern, die die internen Beschr\u00e4nkungen einer Inline-Klasse verletzen k\u00f6nnten. Lesen Sie <a href=\"#jvm-name-support\">unten<\/a> weiter, wie Sie ihn von Java aus nutzbar machen k\u00f6nnen.<\/p>\n<p>Der Wrapper wird nicht immer im Bytecode eliminiert. Dies geschieht nur, wenn es m\u00f6glich ist, und es funktioniert ganz \u00e4hnlich wie bei eingebauten primitiven Typen. Wenn Sie eine Variable vom Typ <code>Color<\/code> definieren oder sie direkt an eine Funktion \u00fcbergeben, wird sie durch den zugrunde liegenden Wert ersetzt:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\nval color = Color(0)        \/\/ primitive\nchangeBackground(color)     \/\/ primitive\n<\/pre>\n<p>In diesem Beispiel hat die <code>Color<\/code>-Variable bei der Kompilierung den Typ <code>Color<\/code>, im Bytecode wird sie aber durch <code>Int<\/code> ersetzt.<\/p>\n<p>Wenn Sie sie jedoch in einer Sammlung speichern oder an eine generische Funktion \u00fcbergeben, wird sie in ein regul\u00e4res Objekt vom Typ <code>Color<\/code> geschachtelt:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\ngenericFunc(color)         \/\/ boxed\nval list = listOf(color)   \/\/ boxed\nval first = list.first()   \/\/ unboxed back to primitive\n<\/pre>\n<p>Das Boxing und Unboxing wird automatisch vom Compiler durchgef\u00fchrt. Sie m\u00fcssen nichts dagegen tun, aber es ist n\u00fctzlich, die Interna zu verstehen.<\/p>\n<h3>\u00c4ndern des JVM-Namens f\u00fcr Java-Aufrufe<\/h3>\n<p><a name = \"jvm-name-support\"><\/a><\/p>\n<p>Ab 1.4.30 k\u00f6nnen Sie den JVM-Namen einer Funktion \u00e4ndern, die eine Inline-Klasse als Parameter annimmt, um sie von Java aus nutzbar zu machen. Standardm\u00e4\u00dfig werden solche Namen gemangelt, um versehentliche Verwendungen aus Java oder widerspr\u00fcchliche \u00dcberladungen zu verhindern (wie <code>changeBackground-euwHqFQ<\/code> im obigen Beispiel).<\/p>\n<p>Wenn Sie eine Funktion mit <code>@JvmName<\/code> annotieren, \u00e4ndert dies den Namen dieser Funktion im Bytecode und erm\u00f6glicht es, sie von Java aus aufzurufen und direkt einen Wert zu \u00fcbergeben:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\n\/\/ Kotlin declarations\ninline class Timeout(val millis: Long)\n\nval Int.millis get() = Timeout(this.toLong())\nval Int.seconds get() = Timeout(this * 1000L)\n\n@JvmName(&quot;greetAfterTimeoutMillis&quot;)\nfun greetAfterTimeout(timeout: Timeout)\n\n\/\/ Kotlin usage\ngreetAfterTimeout(2.seconds)\n\n\/\/ Java usage\ngreetAfterTimeoutMillis(2000);\n<\/pre>\n<p>Wie immer bei einer mit <code>@JvmName<\/code> annotierten Funktion, rufen Sie diese von Kotlin aus mit ihrem Kotlin-Namen auf. Die Verwendung in Kotlin ist typsicher, da Sie nur einen Wert vom Typ <code>Timeout<\/code> als Argument \u00fcbergeben k\u00f6nnen, und die Einheiten sind aus der Verwendung ersichtlich.<\/p>\n<p>Von Java aus k\u00f6nnen Sie einen <code>Long<\/code>-Wert direkt \u00fcbergeben. Das ist nicht mehr typsicher, und deshalb funktioniert es standardm\u00e4\u00dfig auch nicht. Wenn Sie <code>greetAfterTimeout(2)<\/code> im Code sehen, ist es nicht sofort klar, ob es sich um 2 Sekunden, 2 Millisekunden oder 2 Jahre handelt.<\/p>\n<p>Mit der Annotation <em>betonen<\/em> Sie explizit, dass diese Funktion von Java aus aufgerufen werden soll. Ein beschreibender Name hilft, Verwechslungen zu vermeiden: Das Hinzuf\u00fcgen des Suffixes &#8220;Millis&#8221; zum JVM-Namen macht die Einheiten f\u00fcr Java-Benutzer*innen deutlich.<\/p>\n<h3>Init-Bl\u00f6cke<\/h3>\n<p><a name = \"init-blocks\"><\/a><\/p>\n<p>Eine weitere Verbesserung f\u00fcr Inline-Klassen in 1.4.30 ist, dass Sie nun Initialisierungslogik im <code>Init<\/code>-Block definieren k\u00f6nnen:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\ninline class Name(val s: String) {\n   init {\n       require(s.isNotEmpty())\n   }\n}\n<\/pre>\n<p>Dies war bisher nicht erlaubt.<\/p>\n<p>Weitere Details zu Inline-Klassen k\u00f6nnen Sie im entsprechenden <a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/inline-classes.md\" target=\"_blank\" rel=\"noopener\">KEEP<\/a>, in der <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/whatsnew1430.html#improved-inline-classes\" target=\"_blank\" rel=\"noopener\">Dokumentation<\/a> und in der Diskussion unter <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42434\" target=\"_blank\" rel=\"noopener\">diesem Issue<\/a> nachlesen.<\/p>\n<h3>Inline-Wertklassen<\/h3>\n<p><a name = \"inline-value-classes\"><\/a><\/p>\n<p>Kotlin 1.5 stabilisiert das Konzept der Inline-Klassen und macht es zu einem Teil einer allgemeineren Funktion: Value-Klassen.<\/p>\n<p>Bisher stellten &#8220;Inline&#8221;-Klassen ein separates Sprachmerkmal dar, aber sie werden nun zu einer spezifischen JVM-Optimierung f\u00fcr eine Wertklasse mit einem Parameter. Wertklassen stellen ein allgemeineres Konzept dar und werden verschiedene Optimierungen unterst\u00fctzen: Inline-Klassen jetzt und primitive Valhalla-Klassen in der Zukunft, wenn das Projekt Valhalla verf\u00fcgbar wird (mehr dazu <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/02\/new-language-features-preview-in-kotlin-1-4-30\/#valhalla\">unten<\/a>).<\/p>\n<p>Das einzige, was sich f\u00fcr Sie im Moment \u00e4ndert, ist die Syntax. Da eine Inline-Klasse eine optimierte Wertklasse ist, m\u00fcssen Sie sie anders deklarieren als bisher:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\n@JvmInline\nvalue class Color(val rgb: Int)\n<\/pre>\n<p>Sie definieren eine Wertklasse mit einem Konstruktorparameter und annotieren sie mit <code>@JvmInline<\/code>. Wir erwarten, dass jeder diese neue Syntax ab Kotlin 1.5 verwenden wird. Die alte Syntax <code>Inline-Klasse<\/code> wird noch eine Zeit lang funktionieren. Sie wird in 1.5 mit einer Warnung veraltet sein und eine Option enthalten, um alle Ihre Deklarationen automatisch zu migrieren. Sp\u00e4ter wird sie mit einem Fehler verworfen.<\/p>\n<h2>Wertklassen<\/h2>\n<p><a name = \"value-classes\"><\/a><\/p>\n<p>Eine <code>value-<\/code>Klasse repr\u00e4sentiert eine unver\u00e4nderliche Entit\u00e4t mit Daten. Im Moment kann eine <code>value-<\/code>Klasse <em>nur eine<\/em> Eigenschaft enthalten, um den Anwendungsfall der &#8220;alten&#8221; Inline-Klassen zu unterst\u00fctzen.<\/p>\n<p>In zuk\u00fcnftigen Kotlin-Versionen mit voller Unterst\u00fctzung f\u00fcr diese Funktion wird es m\u00f6glich sein, Wertklassen mit vielen Eigenschaften zu definieren. Alle Werte sollten schreibgesch\u00fctzte <code>val<\/code>s sein:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\nvalue class Point(val x: Int, val y: Int)\n<\/pre>\n<p>Werteklassen haben keine Identit\u00e4t: Sie sind vollst\u00e4ndig durch die gespeicherten Daten definiert und === Identit\u00e4tspr\u00fcfungen sind f\u00fcr sie nicht erlaubt. Die == Gleichheitspr\u00fcfung vergleicht automatisch die zugrunde liegenden Daten.<\/p>\n<p>Diese &#8220;identit\u00e4tslose&#8221; Eigenschaft von Wertklassen erm\u00f6glicht bedeutende zuk\u00fcnftige Optimierungen: Mit der Ankunft von Project Valhalla in der JVM k\u00f6nnen Wertklassen im Hintergrund als JVM-Primitivklassen implementiert werden.<\/p>\n<p>Die Unver\u00e4nderlichkeitsbeschr\u00e4nkung und damit die M\u00f6glichkeit von Valhalla-Optimierungen unterscheidet <code>value<\/code>-Klassen von <code>data<\/code>-Klassen.<\/p>\n<h3>Zuk\u00fcnftige Valhalla-Optimierung<\/h3>\n<p><a name = \"valhalla\"><\/a><\/p>\n<p><a href=\"https:\/\/openjdk.java.net\/jeps\/8251554\" target=\"_blank\" rel=\"noopener\">Das Projekt Valhalla<\/a> f\u00fchrt ein neues Konzept in Java und der JVM ein: primitive Klassen.<\/p>\n<p>Das Hauptziel von primitiven Klassen ist es, performante Primitive mit den objektorientierten Vorteilen von regul\u00e4ren JVM-Klassen zu kombinieren. Primitive Klassen sind Datenhalter, deren Instanzen in Variablen oder auf dem Berechnungs-Stack gespeichert werden k\u00f6nnen und auf die direkt, ohne Header und Pointer, zugegriffen werden kann. In dieser Hinsicht \u00e4hneln sie primitiven Werten wie <code>int<\/code>, <code>long<\/code>, etc. (in Kotlin arbeitet man nicht direkt mit primitiven Typen, sondern der Compiler erzeugt sie im Hintergrund).<\/p>\n<p>Ein wichtiger Vorteil von primitiven Klassen ist, dass sie eine flache und dichte Anordnung von Objekten im Arbeitsspeicher erm\u00f6glichen. Derzeit ist <code>Array&lt;Point&gt;<\/code> ein Array von Referenzen. Mit der Valhalla-Unterst\u00fctzung kann die JVM bei der Definition von <code>Point<\/code> als primitive Klasse (in Java-Terminologie) oder als Wertklasse mit der zugrundeliegenden Optimierung (in Kotlin-Terminologie) diese optimieren und ein Array von <code>Point<\/code>s in einem &#8220;flachen&#8221; Layout speichern, als Array von vielen <code>x<\/code>s und <code>y<\/code>s direkt, nicht als Array von Referenzen.<\/p>\n<p>Wir freuen uns sehr auf die kommenden JVM-\u00c4nderungen und wir wollen, dass Kotlin davon profitiert. Gleichzeitig wollen wir unsere Community nicht zwingen, von neuen JVM-Versionen abh\u00e4ngig zu sein, um <code>Value-Klassen<\/code> verwenden zu k\u00f6nnen, und deshalb werden wir sie auch f\u00fcr fr\u00fchere JVM-Versionen unterst\u00fctzen. Beim Kompilieren des Codes f\u00fcr die JVM mit Valhalla-Unterst\u00fctzung werden die neuesten JVM-Optimierungen f\u00fcr Value-Klassen funktionieren.<\/p>\n<h3>Mutierende Methoden<\/h3>\n<p><a name = \"mutating-methods\"><\/a><\/p>\n<p>Es gibt noch viel mehr \u00fcber die Funktionalit\u00e4t von Wertklassen zu sagen. Da Wertklassen &#8220;unver\u00e4nderliche&#8221; Daten darstellen, sind f\u00fcr sie mutierende Methoden, wie in <a href=\"https:\/\/docs.swift.org\/swift-book\/LanguageGuide\/Methods.html\" target=\"_blank\" rel=\"noopener\">Swift<\/a>, m\u00f6glich. Von einer mutierenden Methode spricht man, wenn eine Member-Funktion oder ein Property-Setter eine neue Instanz zur\u00fcckgibt, anstatt eine bestehende zu aktualisieren. Der Hauptvorteil ist, dass man sie mit einer vertrauten Syntax verwenden kann. Dies muss noch in der Sprache prototypisiert werden.<\/p>\n<h3>Weitere Details<\/h3>\n<p><a name = \"read-more-value-classes\"><\/a><\/p>\n<p>Die Annotation <code>@JvmInline<\/code> ist JVM-spezifisch. Auf anderen Backends k\u00f6nnen Wertklassen anders implementiert werden. Zum Beispiel als Swift-Strukturen in Kotlin\/Native.<\/p>\n<p>Die Details zu Wertklassen k\u00f6nnen Sie in der <a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/notes\/value-classes.md\" target=\"_blank\" rel=\"noopener\">Design Note f\u00fcr Kotlin-Wertklassen<\/a> nachlesen oder sich einen Auszug aus dem <a href=\"https:\/\/www.youtube.com\/watch?v=0FF19HJDqMo&amp;t=26m32s\" target=\"_blank\" rel=\"noopener\">Vortrag &#8220;Ein Blick in die Zukunft&#8221;<\/a> von Roman Elizarov ansehen.<\/p>\n<h2>Unterst\u00fctzung f\u00fcr JVM-Records<\/h2>\n<p><a name = \"jvm-records\"><\/a><\/p>\n<p>Eine weitere kommende Verbesserung im JVM-\u00d6kosystem sind <a href=\"https:\/\/openjdk.java.net\/jeps\/395\" target=\"_blank\" rel=\"noopener\">Java-Records<\/a>. Sie sind analog zu den Kotlin-<code>Datenklassen<\/code> und werden haupts\u00e4chlich als einfache Datenhalter verwendet.<\/p>\n<p>Java records don\u2019t follow the JavaBeans convention, and they have <code>x()<\/code> and <code>y()<\/code> methods instead of the familiar <code>getX()<\/code> and <code>getY()<\/code>.<\/p>\n<p>Interoperabilit\u00e4t mit Java war schon immer eine Priorit\u00e4t f\u00fcr Kotlin und wird es auch in Zukunft sein. So &#8220;versteht&#8221; der Kotlin-Code neue Java-Records und sieht sie als Klassen mit Kotlin-Eigenschaften. Dies funktioniert wie bei regul\u00e4ren Java-Klassen, die der JavaBeans-Konvention folgen:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\n\/\/ Java\nrecord Point(int x, int y) { }\n\/\/ Kotlin\nfun foo(point: Point) {\n    point.x \/\/ seen as property\n    point.x() \/\/ also works\n}\n<\/pre>\n<p>Vor allem aus Gr\u00fcnden der Interoperabilit\u00e4t k\u00f6nnen Sie Ihre <code>data<\/code>-Klasse mit <code>@JvmRecord<\/code> annotieren, um neue JVM-Record-Methoden generieren zu lassen:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\n@JvmRecord\ndata class Point(val x: Int, val y: Int)\n<\/pre>\n<p>Die Annotation <code>@JvmRecord<\/code> veranlasst den Compiler, <code>x()<\/code>&#8211; und <code>y()<\/code>-Methoden anstelle der Standardmethoden <code>getX()<\/code> und <code>getY()<\/code> zu generieren. Wir gehen davon aus, dass Sie diese Annotation nur verwenden m\u00fcssen, um die API der Klasse bei der Konvertierung von Java nach Kotlin zu erhalten. In allen anderen Anwendungsf\u00e4llen k\u00f6nnen stattdessen die bekannten <code>data<\/code>-Klassen von Kotlin ohne Probleme verwendet werden.<\/p>\n<p>Diese Annotation ist nur verf\u00fcgbar, wenn Sie Kotlin-Code bis zur Version 15+ von JVM kompilieren. Sie k\u00f6nnen mehr \u00fcber diese Funktion im entsprechenden <a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/jvm-records.md\" target=\"_blank\" rel=\"noopener\">KEEP<\/a> oder in der <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/whatsnew1430.html#jvm-records-support\" target=\"_blank\" rel=\"noopener\">Dokumentation<\/a> lesen, sowie in der Diskussion in <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42430\" target=\"_blank\" rel=\"noopener\">diesem Issue<\/a>.<\/p>\n<h2>Verbesserungen bei Sealed-Interfaces und Sealed-Klassen<\/h2>\n<p><a name = \"sealed-interfaces\"><\/a><\/p>\n<p>Wenn Sie eine Klasse &#8216;sealed&#8217; machen, schr\u00e4nkt dies die Hierarchie auf definierte Unterklassen ein, was l\u00fcckenlos Pr\u00fcfungen von <code>when<\/code> Branches erm\u00f6glicht. In Kotlin 1.4 wird die Sealed-Klassenhierarchie mit zwei Einschr\u00e4nkungen versehen. Erstens kann die oberste Klasse keine Sealed-Interface sein, sondern muss eine Klasse sein. Zweitens sollten sich alle Unterklassen in der gleichen Datei befinden.<\/p>\n<p>Kotlin 1.5 hebt beide Beschr\u00e4nkungen auf: Sie k\u00f6nnen jetzt ein <em>Interface<\/em> &#8216;sealed&#8217; machen. Die Unterklassen (sowohl zu Sealed-Klassen als auch zu Sealed-Interfaces) sollten sich in der gleichen Kompilierungseinheit und im gleichen Paket wie die Oberklasse befinden, aber sie k\u00f6nnen jetzt in <em>verschiedenen<\/em> Dateien liegen.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\nsealed interface Expr\ndata class Const(val number: Double) : Expr\ndata class Sum(val e1: Expr, val e2: Expr) : Expr\nobject NotANumber : Expr\n\nfun eval(expr: Expr): Double = when(expr) {\n    is Const -&gt; expr.number\n    is Sum -&gt; eval(expr.e1) + eval(expr.e2)\n    NotANumber -&gt; Double.NaN\n}\n<\/pre>\n<p>Sealed-Klassen und jetzt auch Interfaces sind n\u00fctzlich, um abstrakte Datentyphierarchien (ADT) zu definieren.<\/p>\n<p>Ein weiterer wichtiger Anwendungsfall, der jetzt mit Sealed-Interfaces gut adressiert werden kann, ist das Schlie\u00dfen eines Interfaces f\u00fcr die Vererbung and Implementierung au\u00dferhalb der Bibliothek. Die Definition eines Interfaces als &#8216;sealed&#8217; schr\u00e4nkt ihre Implementierung auf dieselbe Kompilierungseinheit und dasselbe Paket ein, was im Fall einer Bibliothek eine Implementierung au\u00dferhalb der Bibliothek unm\u00f6glich macht.<\/p>\n<p>Das Interface <code>Job<\/code> aus dem Paket <code>kotlinx.coroutines<\/code> ist beispielsweise nur f\u00fcr die Implementierung innerhalb der Bibliothek <code>kotlinx.coroutines<\/code> vorgesehen. Dadurch, dass sie jetzt <code>sealed<\/code> ist, wird diese Intention explizit gemacht:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\npackage kotlinx.coroutines\nsealed interface Job { ... }\n<\/pre>\n<p>Als Benutzer der Bibliothek ist es Ihnen nicht mehr erlaubt, eine eigene Unterklasse von <code>Job<\/code> zu definieren. Dies war immer &#8220;implizit&#8221;, aber mit Sealed-Interfaces kann der Compiler dies formal verbieten.<\/p>\n<h3>Zuk\u00fcnftige Verwendung der JVM-Unterst\u00fctzung<\/h3>\n<p><a name = \"new-sealed-jvm-support\"><\/a><\/p>\n<p>Die Unterst\u00fctzung f\u00fcr Sealed-Klassen wurde in Java 15 und auf der JVM eingef\u00fchrt. In Zukunft werden wir die nat\u00fcrliche JVM-Unterst\u00fctzung f\u00fcr Sealed-Klassen nutzen, wenn Sie Kotlin-Code auf der neuesten JVM kompilieren (h\u00f6chstwahrscheinlich JVM 17 oder sp\u00e4ter, wenn diese Funktion stabil wird).<\/p>\n<p>In Java listen Sie explizit alle Unterklassen der gegebenen Sealed-Klasse oder -Interface auf:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\n\/\/ Java\npublic sealed interface Expression\n    permits Const, Sum, NotANumber { ... }\n<\/pre>\n<p>Diese Information wird in der Klassendatei mit dem neuen Attribut <code>PermittedSubclasses<\/code> gespeichert. Die JVM erkennt Sealed-Klassen zur Laufzeit und verhindert deren Erweiterung durch nicht erlaubte Unterklassen.<\/p>\n<p>Wenn Sie Kotlin in der Zukunft in die neueste JVM kompilieren, wird diese neue JVM-Unterst\u00fctzung f\u00fcr Sealed-Klassen verwendet. Im Hintergrund wird der Compiler eine Liste der erlaubten Unterklassen im Bytecode generieren, um sicherzustellen, dass die JVM-Unterst\u00fctzung und zus\u00e4tzliche Laufzeitpr\u00fcfungen vorhanden sind.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\n\/\/ f\u00fcr JVM 17 oder sp\u00e4ter\nExpr::class.java.permittedSubclasses \/\/ [Const, Sum, NotANumber]\n<\/pre>\n<p>In Kotlin m\u00fcssen Sie die Liste der Unterklassen nicht angeben! Der Compiler generiert die Liste basierend auf den deklarierten Unterklassen im gleichen Paket.<\/p>\n<p>Die M\u00f6glichkeit, die Unterklassen f\u00fcr eine Superklasse oder ein Interface explizit anzugeben, k\u00f6nnte sp\u00e4ter als optionale Angabe hinzugef\u00fcgt werden. Im Moment vermuten wir, dass es nicht notwendig sein wird, aber wir w\u00fcrden uns freuen, von Ihren Anwendungsf\u00e4llen zu h\u00f6ren, und ob Sie diese Funktionalit\u00e4t ben\u00f6tigen!<\/p>\n<p>Beachten Sie, dass es f\u00fcr \u00e4ltere JVM-Versionen theoretisch m\u00f6glich ist, eine Java-Subklasse zur Kotlin-Sealed-Interface zu definieren, aber tun Sie es nicht! Da die JVM-Unterst\u00fctzung f\u00fcr erlaubte Unterklassen noch nicht verf\u00fcgbar ist, wird diese Einschr\u00e4nkung nur durch den Kotlin-Compiler erzwungen. Wir werden IDE-Warnungen hinzuf\u00fcgen, um zu verhindern, dass dies versehentlich geschieht. In Zukunft wird der neue Mechanismus f\u00fcr die neuesten JVM-Versionen verwendet werden, um sicherzustellen, dass es keine &#8220;unerlaubten&#8221; Unterklassen von Java gibt.<\/p>\n<p>Mehr \u00fcber Sealed-Interfaces und die gelockerten Einschr\u00e4nkungen f\u00fcr Sealed-Klassen k\u00f6nnen Sie im entsprechenden <a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/sealed-interface-freedom.md\" target=\"_blank\" rel=\"noopener\">KEEP<\/a> oder in der <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/whatsnew1430.html#sealed-interfaces\" target=\"_blank\" rel=\"noopener\">Dokumentation<\/a> nachlesen, sowie die Diskussion in <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42433\" target=\"_blank\" rel=\"noopener\">diesem Issue<\/a> verfolgen.<\/p>\n<h2>Wie Sie die neuen Funktionen ausprobieren k\u00f6nnen<\/h2>\n<p><a name = \"how-to-try\"><\/a><\/p>\n<p>Sie m\u00fcssen Kotlin 1.4.30 verwenden. Geben Sie die <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/compiler-reference.html#-language-version-version\" target=\"_blank\" rel=\"noopener\">Sprachversion<\/a> 1.5 an, um die neuen Funktionen zu aktivieren:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\ncompileKotlin {\n    kotlinOptions {\n        languageVersion = &quot;1.5&quot;\n        apiVersion = &quot;1.5&quot;\n    }\n}\n<\/pre>\n<p>Um JVM-Records auszuprobieren, m\u00fcssen Sie zus\u00e4tzlich jvmTarget 15 verwenden und die JVM-Vorschau-Funktionen aktivieren: F\u00fcgen Sie die Compiler-Optionen <code>-language-version 1.5<\/code> und &#8211;<code>Xjvm-enable-preview<\/code> hinzu.<\/p>\n<h3>Pre-Release-Hinweise<\/h3>\n<p>Beachten Sie, dass die Unterst\u00fctzung f\u00fcr die neuen Funktionen experimentell ist und die Unterst\u00fctzung der Sprachversion 1.5 sich im Pre-Release-Status befindet. Die Sprachversion auf 1.5 im Kotlin 1.4.30 Compiler einzustellen ist vergleichbar mit der 1.5-M0-Vorschau auszuprobieren. Die Abw\u00e4rtskompatibilit\u00e4tsgarantien gelten nicht f\u00fcr Pre-Release-Versionen. Die Funktionen und die API k\u00f6nnen sich in nachfolgenden Versionen \u00e4ndern. Wenn wir eine endg\u00fcltige Kotlin 1.5-RC erreichen, werden alle Bin\u00e4rdateien, die mit Pre-Release-Versionen erzeugt wurden, vom Compiler ge\u00e4chtet und Sie m\u00fcssen alles, was mit 1.5-Mx kompiliert wurde, neu kompilieren.<\/p>\n<h3>Geben Sie uns Feedback<\/h3>\n<p>Bitte probieren Sie die in diesem Beitrag beschriebenen neuen Funktionen aus und geben Sie uns Ihr Feedback! Sie k\u00f6nnen weitere Details in KEEPs finden und sich an den Diskussionen in YouTrack beteiligen. Sie k\u00f6nnen auch neue Probleme melden, wenn etwas bei Ihnen nicht funktioniert. Bitte teilen Sie Ihre Erkenntnisse dar\u00fcber mit, wie gut die neuen Funktionen Anwendungsf\u00e4lle in Ihren Projekten adressieren!<\/p>\n<p>Weitere Lekt\u00fcre und Diskussionen:<\/p>\n<ul>\n<li><a href=\"https:\/\/kotlinlang.org\/docs\/reference\/whatsnew1430.html\" target=\"_blank\" rel=\"noopener\">Dokumentationsseite &#8220;Was ist neu&#8221;<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/inline-classes.md\" target=\"_blank\" rel=\"noopener\">Inline-Klassen KEEP<\/a>; Diskussion: <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42434\" target=\"_blank\" rel=\"noopener\">KT-42434<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/notes\/value-classes.md\" target=\"_blank\" rel=\"noopener\">Design-Dokument f\u00fcr Wertklassen<\/a>; Diskussion in <a href=\"https:\/\/github.com\/Kotlin\/KEEP\/issues\/237\" target=\"_blank\" rel=\"noopener\">KEEP<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/jvm-records.md\" target=\"_blank\" rel=\"noopener\">JVM-Records KEEP<\/a>; Diskussion: <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42430\" target=\"_blank\" rel=\"noopener\">KT-42430<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/sealed-interface-freedom.md\" target=\"_blank\" rel=\"noopener\">Sealed-Interfaces und Sealed-Klassen KEEP<\/a>; Diskussion: <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42433\" target=\"_blank\" rel=\"noopener\">KT-42433<\/a>.<\/li>\n<\/ul>\n","protected":false},"author":1132,"featured_media":113654,"comment_status":"closed","ping_status":"closed","template":"","categories":[907],"tags":[],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/kotlin\/127683"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/kotlin"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/types\/kotlin"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/users\/1132"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/comments?post=127683"}],"version-history":[{"count":1,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/kotlin\/127683\/revisions"}],"predecessor-version":[{"id":127684,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/kotlin\/127683\/revisions\/127684"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/media\/113654"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/media?parent=127683"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/categories?post=127683"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/tags?post=127683"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/cross-post-tag?post=127683"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}