{"id":121427,"date":"2021-03-04T23:25:59","date_gmt":"2021-03-04T22:25:59","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=121427"},"modified":"2021-03-04T23:25:59","modified_gmt":"2021-03-04T22:25:59","slug":"demonstracao-dos-novos-recursos-de-linguagem-no-kotlin-1-4-30","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/pt-br\/kotlin\/2021\/03\/demonstracao-dos-novos-recursos-de-linguagem-no-kotlin-1-4-30\/","title":{"rendered":"Demonstra\u00e7\u00e3o dos novos recursos de linguagem no Kotlin 1.4.30"},"content":{"rendered":"<p>Estamos planejando adicionar novos recursos de linguagem ao Kotlin 1.5, e voc\u00ea j\u00e1 pode experiment\u00e1-los no Kotlin 1.4.30:<\/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\">Estabiliza\u00e7\u00e3o de classes inline value<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/02\/new-language-features-preview-in-kotlin-1-4-30\/#jvm-records\">Suporte experimental para registros de JVM<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/02\/new-language-features-preview-in-kotlin-1-4-30\/#sealed-interfaces\">Suporte experimental para interfaces sealed e outras melhorias para classes sealed<\/a><\/li>\n<\/ul>\n<p>Para experimentar esses novos recursos, voc\u00ea precisa <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/02\/new-language-features-preview-in-kotlin-1-4-30\/#how-to-try\">especificar a vers\u00e3o de linguagem 1.5<\/a>.<\/p>\n<p>A nova <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2020\/10\/new-release-cadence-for-kotlin-and-the-intellij-kotlin-plugin\/\">cad\u00eancia de lan\u00e7amentos<\/a> significa que o Kotlin 1.5 ser\u00e1 lan\u00e7ado em alguns meses, mas novos recursos j\u00e1 est\u00e3o dispon\u00edveis para demonstra\u00e7\u00e3o na vers\u00e3o 1.4.30. Como seu feedback inicial \u00e9 essencial para n\u00f3s, n\u00e3o deixe de experimentar esses novos recursos agora mesmo!<\/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>Estabiliza\u00e7\u00e3o de classes inline value<\/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\">Classes inline<\/a> est\u00e3o dispon\u00edveis em <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/evolution\/components-stability.html#stability-levels-explained\" target=\"_blank\" rel=\"noopener\">Alpha<\/a> desde o Kotlin 1.3 e, na vers\u00e3o 1.4.30, elas foram promovidas para <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/evolution\/components-stability.html#stability-levels-explained\" target=\"_blank\" rel=\"noopener\">Beta<\/a>.<\/p>\n<p>O Kotlin 1.5 estabiliza o conceito de classes inline, mas o torna parte de um recurso mais geral, <em>classes value<\/em>, que descreveremos mais adiante neste post.<\/p>\n<p>Come\u00e7aremos com uma recapitula\u00e7\u00e3o sobre como funcionam as classes inline. Se voc\u00ea j\u00e1 est\u00e1 familiarizado com classes inline, pode pular esta se\u00e7\u00e3o e ir diretamente para as <a href=\"#jvm-name-support\">novas altera\u00e7\u00f5es<\/a>.<\/p>\n<p>Como lembrete r\u00e1pido, uma classe inline elimina um wrapper em torno de um valor:<\/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>Uma classe inline pode ser um wrapper para um tipo primitivo e para qualquer tipo de refer\u00eancia, como <code>String<\/code>.<\/p>\n<p>O compiler substitui inst\u00e2ncias da classe inline (em nosso exemplo, a inst\u00e2ncia <code>Color<\/code>) pelo tipo subjacente (<code>Int<\/code>) no bytecode, quando poss\u00edvel:<\/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>Nos bastidores, o compiler gera a fun\u00e7\u00e3o <code>changeBackground<\/code> com um nome deformado usando <code>Int<\/code> como um par\u00e2metro e transmite a constante <code>255<\/code> diretamente sem criar um wrapper no local de chamada:<\/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) \/\/ no extra object is allocated! \n<\/pre>\n<p>O nome \u00e9 deformado para permitir a sobrecarga cont\u00ednua de fun\u00e7\u00f5es que usam inst\u00e2ncias de diferentes classes inline e para evitar invoca\u00e7\u00f5es acidentais do c\u00f3digo Java que podem violar as restri\u00e7\u00f5es internas de uma classe inline. Leia <a href=\"#jvm-name-support\">abaixo<\/a> para descobrir como torn\u00e1-lo utiliz\u00e1vel em Java.<\/p>\n<p>O wrapper nem sempre \u00e9 eliminado no bytecode. Isso acontece apenas quando poss\u00edvel e funciona de forma muito semelhante a tipos primitivos integrados. Quando voc\u00ea define uma vari\u00e1vel do tipo <code>Color<\/code> ou a transmite diretamente para uma fun\u00e7\u00e3o, ela \u00e9 substitu\u00edda pelo valor subjacente:<\/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>Neste exemplo, a vari\u00e1vel <code>color<\/code> tem o tipo <code>Color<\/code> durante a compila\u00e7\u00e3o, mas \u00e9 substitu\u00edda por <code>Int<\/code> no bytecode.<\/p>\n<p>Por\u00e9m, se voc\u00ea a armazenar em uma cole\u00e7\u00e3o ou transmiti-la para uma fun\u00e7\u00e3o gen\u00e9rica, ela ser\u00e1 empacotada em um objeto regular do tipo <code>Color<\/code>:<\/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>O empacotamento e o desempacotamento s\u00e3o feitos automaticamente pelo compiler. Voc\u00ea n\u00e3o precisa fazer nada a respeito, mas \u00e9 \u00fatil entender os detalhes internos.<\/p>\n<h3>Alterando o nome JVM para chamadas Java<\/h3>\n<p><a name = \"jvm-name-support\"><\/a><\/p>\n<p>A partir da vers\u00e3o 1.4.30, voc\u00ea pode alterar o nome JVM de uma fun\u00e7\u00e3o usando uma classe inline como par\u00e2metro para torn\u00e1-la utiliz\u00e1vel em Java. Por padr\u00e3o, esses nomes s\u00e3o deformados para evitar usos acidentais do Java ou sobrecargas conflitantes (como <code>changeBackground-euwHqFQ<\/code> no exemplo acima).<\/p>\n<p>Se voc\u00ea anotar uma fun\u00e7\u00e3o com <code>@JvmName<\/code>, isso alterar\u00e1 o nome dessa fun\u00e7\u00e3o no bytecode e permitir\u00e1 sua chamada no Java e a transmiss\u00e3o direta de um valor:<\/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>Como sempre com uma fun\u00e7\u00e3o anotada com <code>@JvmName<\/code>, no Kotlin, voc\u00ea a chama pelo seu nome Kotlin. O uso do Kotlin \u00e9 seguro para tipos, j\u00e1 que voc\u00ea s\u00f3 pode transmitir um valor do tipo <code>Timeout<\/code> como um argumento, e as unidades s\u00e3o \u00f3bvias pelo uso.<\/p>\n<p>No Java, voc\u00ea pode transmitir um valor <code>long<\/code> diretamente. Ele n\u00e3o \u00e9 mais seguro para tipos e \u00e9 por isso que n\u00e3o funciona por padr\u00e3o. Se voc\u00ea vir <code>greetAfterTimeout(2)<\/code> no c\u00f3digo, n\u00e3o fica imediatamente \u00f3bvio se o 2 refere-se a segundos, milissegundos ou anos.<\/p>\n<p>Ao fornecer a anota\u00e7\u00e3o, voc\u00ea <em>enfatiza<\/em> explicitamente que pretende que essa fun\u00e7\u00e3o seja chamada do Java. Um nome descritivo ajuda a evitar confus\u00e3o: adicionar o sufixo &#8220;Millis&#8221; ao nome JVM torna as unidades claras para usu\u00e1rios Java.<\/p>\n<h3>Blocos Init<\/h3>\n<p><a name = \"init-blocks\"><\/a><\/p>\n<p>Outra melhoria para classes inline na vers\u00e3o 1.4.30 \u00e9 que agora voc\u00ea pode definir a l\u00f3gica de inicializa\u00e7\u00e3o no bloco <code>init<\/code>:<\/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>Antes, isso era proibido.<\/p>\n<p>Voc\u00ea pode ler mais detalhes sobre classes inline no <a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/inline-classes.md\" target=\"_blank\" rel=\"noopener\">KEEP<\/a> correspondente, na <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/whatsnew1430.html#improved-inline-classes\" target=\"_blank\" rel=\"noopener\">documenta\u00e7\u00e3o<\/a> e na discuss\u00e3o <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42434\" target=\"_blank\" rel=\"noopener\">deste issue<\/a>.<\/p>\n<h3>Classes inline value<\/h3>\n<p><a name = \"inline-value-classes\"><\/a><\/p>\n<p>O Kotlin 1.5 estabiliza o conceito de classes inline, mas o torna parte de um recurso mais geral, classes value.<\/p>\n<p>At\u00e9 agora, as classes &#8220;inline&#8221; constitu\u00edam um recurso de linguagem separado, mas agora est\u00e3o se tornando uma otimiza\u00e7\u00e3o JVM espec\u00edfica para uma classe value com um s\u00f3 par\u00e2metro. Classes value representam um conceito mais geral e suportar\u00e3o diferentes otimiza\u00e7\u00f5es: classes inline agora e classes primitivas Valhalla no futuro quando o projeto Valhalla estiver dispon\u00edvel (mais sobre isso <a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2021\/02\/new-language-features-preview-in-kotlin-1-4-30\/#valhalla\">abaixo<\/a>).<\/p>\n<p>A \u00fanica coisa que muda para voc\u00ea no momento \u00e9 a sintaxe. Como uma classe inline \u00e9 uma classe de valor otimizado, voc\u00ea precisa declar\u00e1-la de forma diferente do que antes:<\/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>Voc\u00ea define uma classe value com um par\u00e2metro do construtor e a anota com <code>@JvmInline<\/code>. Esperamos que todos usem essa nova sintaxe a partir do Kotlin 1.5. A classe <code>inline<\/code> com sintaxe antiga continuar\u00e1 a funcionar por um certo tempo. Ela ser\u00e1 descontinuada com um aviso na vers\u00e3o 1.5, que incluir\u00e1 uma op\u00e7\u00e3o para migrar todas as suas declara\u00e7\u00f5es automaticamente. Posteriormente, ela ser\u00e1 descontinuada com um erro.<\/p>\n<h2>Classes value<\/h2>\n<p><a name = \"value-classes\"><\/a><\/p>\n<p>Uma classe <code>value<\/code> representa uma entidade imut\u00e1vel com dados. No momento, uma classe <code>value<\/code> pode conter <em>apenas uma<\/em> propriedade para suportar o caso de uso de classes inline &#8220;antigas&#8221;.<\/p>\n<p>Nas vers\u00f5es futuras do Kotlin com suporte total para esse recurso, ser\u00e1 poss\u00edvel definir classes value com muitas propriedades. Todos os valores devem ser <code>val<\/code>s somente leitura:<\/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>Classes value n\u00e3o t\u00eam identidade: elas s\u00e3o completamente definidas pelos dados armazenados e verifica\u00e7\u00f5es de identidade === n\u00e3o s\u00e3o permitidos para elas. A verifica\u00e7\u00e3o de igualdade == compara automaticamente os dados subjacentes.<\/p>\n<p>Essa qualidade \u201csem identidade\u201d das classes value permite otimiza\u00e7\u00f5es futuras significativas: a chegada do projeto Valhalla \u00e0 JVM permitir\u00e1 que as classes value sejam implementadas como classes primitivas JVM nos bastidores.<\/p>\n<p>A restri\u00e7\u00e3o de imutabilidade e, portanto, a possibilidade de otimiza\u00e7\u00f5es para o Valhalla, torna as classes <code>value<\/code> diferentes das classes <code>data<\/code>.<\/p>\n<h3>Otimiza\u00e7\u00e3o futura para Valhalla<\/h3>\n<p><a name = \"valhalla\"><\/a><\/p>\n<p>O <a href=\"https:\/\/openjdk.java.net\/jeps\/8251554\" target=\"_blank\" rel=\"noopener\">Projeto Valhalla<\/a> introduz um novo conceito para Java e JVM: classes primitivas.<\/p>\n<p>O principal objetivo das classes primitivas \u00e9 combinar primitivas de grande desempenho com os benef\u00edcios orientados a objetos das classes JVM regulares. Classes primitivas s\u00e3o portadores de dados cujas inst\u00e2ncias podem ser armazenadas em vari\u00e1veis, na pilha de computa\u00e7\u00e3o, e operadas diretamente, sem cabe\u00e7alhos e ponteiros. Nesse sentido, elas s\u00e3o semelhantes a valores primitivos, como <code>int<\/code>, <code>long<\/code>, etc. (no Kotlin, voc\u00ea n\u00e3o trabalha com tipos primitivos diretamente, mas o compilador os gera nos bastidores).<\/p>\n<p>Uma vantagem importante das classes primitivas \u00e9 que elas permitem o layout simples e denso de objetos na mem\u00f3ria. No momento, <code>Array&lt;Point&gt;<\/code> \u00e9 um conjunto de refer\u00eancias. Com suporte ao Valhalla, ao definir <code>Point<\/code> como uma classe primitiva (na terminologia Java) ou como uma classe value com otimiza\u00e7\u00e3o subjacente (na terminologia Kotlin), a JVM pode otimiz\u00e1-la e armazenar uma matriz de <code>Point<\/code>s em um layout &#8220;simples&#8221;, como uma matriz de muitos <code>x<\/code>s e <code>y<\/code>s diretamente, e n\u00e3o como uma matriz de refer\u00eancias.<\/p>\n<p>Estamos realmente ansiosos para as pr\u00f3ximas mudan\u00e7as na JVM e queremos que o Kotlin se beneficie com todas elas. Ao mesmo tempo, n\u00e3o queremos for\u00e7ar nossa comunidade a depender das novas vers\u00f5es de JVM para usar classes <code>value<\/code> e, portanto, ofereceremos suporte para as vers\u00f5es JVM anteriores tamb\u00e9m. Ao compilar o c\u00f3digo para a JVM com suporte para Valhalla, as otimiza\u00e7\u00f5es mais recentes da JVM funcionar\u00e3o para as classes value.<\/p>\n<h3>M\u00e9todos mutantes<\/h3>\n<p><a name = \"mutating-methods\"><\/a><\/p>\n<p>H\u00e1 muito mais a dizer sobre a funcionalidade das classes value. Como as classes value representam dados &#8220;imut\u00e1veis&#8221;, m\u00e9todos mutantes, como aqueles em <a href=\"https:\/\/docs.swift.org\/swift-book\/LanguageGuide\/Methods.html\" target=\"_blank\" rel=\"noopener\">Swift<\/a>, s\u00e3o poss\u00edveis para elas. Um m\u00e9todo mutante \u00e9 quando uma fun\u00e7\u00e3o membro ou setter de propriedade retorna uma nova inst\u00e2ncia em vez de atualizar uma existente, e o principal benef\u00edcio \u00e9 que voc\u00ea os usa com uma sintaxe familiar. Isso ainda precisa ser prototipado na linguagem.<\/p>\n<h3>Mais detalhes<\/h3>\n<p><a name = \"read-more-value-classes\"><\/a><\/p>\n<p>A anota\u00e7\u00e3o <code>@JvmInline<\/code> \u00e9 espec\u00edfica para JVM. Em outros back-ends, as classes value podem ser implementadas de maneira diferente. Por exemplo, como estruturas Swift em Kotlin\/Native.<\/p>\n<p>Voc\u00ea pode ler os detalhes sobre classes value na <a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/notes\/value-classes.md\" target=\"_blank\" rel=\"noopener\">Nota de design para classes value Kotlin<\/a> ou pode assistir a um trecho da conversa <a href=\"https:\/\/www.youtube.com\/watch?v=0FF19HJDqMo&amp;t=26m32s\" target=\"_blank\" rel=\"noopener\">\u201cUm olhar para o futuro\u201d<\/a> de Roman Elizarov.<\/p>\n<h2>Suporte para registros JVM<\/h2>\n<p><a name = \"jvm-records\"><\/a><\/p>\n<p>Outra melhoria futura no ecossistema JVM s\u00e3o os <a href=\"https:\/\/openjdk.java.net\/jeps\/395\" target=\"_blank\" rel=\"noopener\">registros Java<\/a>. Eles s\u00e3o an\u00e1logos \u00e0s classes <code>data<\/code> do Kotlin e, em ess\u00eancia, s\u00e3o portadores de dados.<\/p>\n<p>Os registros Java n\u00e3o seguem a conven\u00e7\u00e3o JavaBeans e t\u00eam os m\u00e9todos <code>x()<\/code> and <code>y()<\/code> em vez dos familiares <code>getX()<\/code> and <code>getY()<\/code>.<\/p>\n<p>A interoperabilidade com Java sempre foi e continua sendo uma prioridade para o Kotlin. Portanto, o c\u00f3digo Kotlin &#8220;entende&#8221; os novos registros Java e os v\u00ea como classes com propriedades Kotlin. Isso funciona como para classes Java regulares seguindo a conven\u00e7\u00e3o JavaBeans:<\/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>Principalmente por raz\u00f5es de interoperabilidade, voc\u00ea pode anotar sua classe <code>data<\/code> com <code>@JvmRecord<\/code> para ter novos m\u00e9todos de registros JVM gerados:<\/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>A anota\u00e7\u00e3o <code>@JvmRecord<\/code> faz com que o compilador gere m\u00e9todos <code>x()<\/code> e <code>y()<\/code> em vez dos m\u00e9todos <code>getX()<\/code> e <code>getY()<\/code> padr\u00e3o. Presumimos que voc\u00ea s\u00f3 precisa usar essa anota\u00e7\u00e3o para preservar a API da classe ao convert\u00ea-la de Java em Kotlin. Em todos os outros casos de uso, as classes <code>data<\/code> familiares do Kotlin podem ser usadas sem problemas.<\/p>\n<p>Essa anota\u00e7\u00e3o estar\u00e1 dispon\u00edvel apenas se voc\u00ea compilar o c\u00f3digo Kotlin para a vers\u00e3o 15+ da vers\u00e3o JVM. Voc\u00ea pode ler mais sobre este recurso no <a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/jvm-records.md\" target=\"_blank\" rel=\"noopener\">KEEP<\/a> correspondente ou na <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/whatsnew1430.html#jvm-records-support\" target=\"_blank\" rel=\"noopener\">documenta\u00e7\u00e3o<\/a>, bem como na discuss\u00e3o <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42430\" target=\"_blank\" rel=\"noopener\">deste issue<\/a>.<\/p>\n<h2>Melhorias em interfaces e classes sealed<\/h2>\n<p><a name = \"sealed-interfaces\"><\/a><\/p>\n<p>Quando voc\u00ea cria uma classe sealed, ela restringe a hierarquia a subclasses definidas, o que permite verifica\u00e7\u00f5es exaustivas em branches <code>when<\/code>. No Kotlin 1.4, a hierarquia de classes selada vem com duas restri\u00e7\u00f5es. Em primeiro lugar, a classe superior n\u00e3o pode ser uma interface sealed, ela deve ser uma classe. Em segundo lugar, todas as subclasses devem estar localizadas no mesmo arquivo.<\/p>\n<p>O Kotlin 1.5 remove ambas as restri\u00e7\u00f5es: agora voc\u00ea pode tornar uma <em>interface<\/em> sealed. As subclasses (tanto para classes seladas quanto para interfaces sealed) devem estar localizadas na mesma unidade de compila\u00e7\u00e3o e no mesmo pacote da superclasse, mas agora podem estar localizadas em arquivos <em>diferentes<\/em>.<\/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>Classes sealed, e agora interfaces, s\u00e3o \u00fateis para definir hierarquias de tipo abstrato de dados (ADT).<\/p>\n<p>Outro caso de uso importante que agora pode ser bem endere\u00e7ado com interfaces sealed \u00e9 fechar uma interface para heran\u00e7a e implementa\u00e7\u00e3o fora da biblioteca. Definir uma interface como sealed restringe sua implementa\u00e7\u00e3o \u00e0 mesma unidade de compila\u00e7\u00e3o e ao mesmo pacote, o que, no caso de uma biblioteca, torna imposs\u00edvel a implementa\u00e7\u00e3o fora da biblioteca.<\/p>\n<p>Por exemplo, a interface <code>Job<\/code> do pacote <code>kotlinx.coroutines<\/code> destina-se apenas a ser implementada dentro da biblioteca <code>kotlinx.coroutines<\/code>. Torn\u00e1-la <code>sealed<\/code> torna essa inten\u00e7\u00e3o expl\u00edcita:<\/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>Como usu\u00e1rio da biblioteca, voc\u00ea n\u00e3o tem mais permiss\u00e3o para definir sua pr\u00f3pria subclasse de <code>Job<\/code>. Isso sempre foi &#8220;impl\u00edcito&#8221;, mas com interfaces sealed, o compiler pode proibir isso formalmente.<\/p>\n<h3>Usando o suporte da JVM no futuro<\/h3>\n<p><a name = \"new-sealed-jvm-support\"><\/a><\/p>\n<p>O suporte de demonstra\u00e7\u00e3o para classes sealed foi introduzido no Java 15 e na JVM. No futuro, usaremos o suporte da JVM natural para classes sealed se voc\u00ea compilar o c\u00f3digo Kotlin para a JVM mais recente (provavelmente JVM 17 ou posterior, quando esse recurso se tornar est\u00e1vel).<\/p>\n<p>Em Java, voc\u00ea lista explicitamente todas as subclasses da classe ou interface sealed fornecida:<\/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>Essas informa\u00e7\u00f5es s\u00e3o armazenadas no arquivo de classe usando o novo atributo <code>PermittedSubclasses<\/code>. A JVM reconhece classes sealed em tempo de execu\u00e7\u00e3o e evita sua extens\u00e3o por subclasses n\u00e3o autorizadas.<\/p>\n<p>No futuro, quando voc\u00ea compilar o Kotlin para a JVM mais recente, esse novo suporte da JVM para classes sealed ser\u00e1 usado. Nos bastidores, o compiler gerar\u00e1 uma lista de subclasses permitidas no bytecode para garantir que haja suporte da JVM e verifica\u00e7\u00f5es adicionais de tempo de execu\u00e7\u00e3o.<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\n\/\/ for JVM 17 or later\nExpr::class.java.permittedSubclasses \/\/ [Const, Sum, NotANumber]\n<\/pre>\n<p>No Kotlin, voc\u00ea n\u00e3o precisa especificar a lista de subclasses. O compiler gerar\u00e1 essa lista com base nas subclasses declaradas no mesmo pacote.<\/p>\n<p>A capacidade de especificar explicitamente as subclasses de uma superclasse ou interface pode ser adicionada posteriormente como uma especifica\u00e7\u00e3o opcional. No momento, suspeitamos que isso n\u00e3o ser\u00e1 necess\u00e1rio, mas gostar\u00edamos de saber mais sobre seus casos de uso e se voc\u00ea precisa dessa funcionalidade!<\/p>\n<p>Observe que, para vers\u00f5es JVM mais antigas, \u00e9 teoricamente poss\u00edvel definir uma subclasse Java para a interface sealed Kotlin, mas n\u00e3o fa\u00e7a isso. Como o suporte da JVM para subclasses permitidas ainda n\u00e3o est\u00e1 dispon\u00edvel, essa restri\u00e7\u00e3o \u00e9 aplicada apenas pelo compilador Kotlin. Adicionaremos avisos do IDE para evitar que isso seja feito acidentalmente. No futuro, o novo mecanismo ser\u00e1 usado para as vers\u00f5es mais recentes da JVM para garantir que n\u00e3o haja subclasses &#8220;n\u00e3o autorizadas&#8221; do Java.<\/p>\n<p>Voc\u00ea pode ler mais sobre interfaces sealed e as restri\u00e7\u00f5es de classes sealed afrouxadas no <a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/sealed-interface-freedom.md\" target=\"_blank\" rel=\"noopener\">KEEP<\/a> correspondente ou na <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/whatsnew1430.html#sealed-interfaces\" target=\"_blank\" rel=\"noopener\">documenta\u00e7\u00e3o<\/a> e veja a discuss\u00e3o <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42433\" target=\"_blank\" rel=\"noopener\">neste issue<\/a>.<\/p>\n<h2>Como experimentar os novos recursos<\/h2>\n<p><a name = \"how-to-try\"><\/a><\/p>\n<p>Voc\u00ea precisa usar o Kotlin 1.4.30. Especifique a <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/compiler-reference.html#-language-version-version\" target=\"_blank\" rel=\"noopener\">vers\u00e3o<\/a> 1.5 da linguagem para habilitar os novos recursos:<\/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>Para experimentar os registros JVM, voc\u00ea tamb\u00e9m precisa usar jvmTarget 15 e habilitar os recursos de demonstra\u00e7\u00e3o da JVM: adicione as op\u00e7\u00f5es do compilador <code>-language-version 1.5<\/code> e <code>-Xjvm-enable-preview<\/code>.<\/p>\n<h3>Notas de pr\u00e9-lan\u00e7amento<\/h3>\n<p>Observe que o suporte para os novos recursos \u00e9 experimental, e o suporte \u00e0 vers\u00e3o 1.5 da linguagem est\u00e1 no status de pr\u00e9-lan\u00e7amento. Definir a vers\u00e3o da linguagem para 1.5 no compiler Kotlin 1.4.30 \u00e9 equivalente a usar a vers\u00e3o de demonstra\u00e7\u00e3o 1.5 M0. As garantias de compatibilidade retroativa n\u00e3o abrangem vers\u00f5es de pr\u00e9-lan\u00e7amento. Os recursos e a API podem mudar nas vers\u00f5es subsequentes. Quando chegarmos a um Kotlin 1.5-RC final, todos os bin\u00e1rios produzidos pelas vers\u00f5es de pr\u00e9-lan\u00e7amento ser\u00e3o proibidos pelo compilador, e voc\u00ea precisar\u00e1 recompilar tudo o que foi compilado pelo 1.5\u2011Mx.<\/p>\n<h3>Compartilhe suas opini\u00f5es<\/h3>\n<p>Experimente os novos recursos descritos neste post e compartilhe seu feedback. Voc\u00ea pode encontrar mais detalhes em KEEPs e participar das discuss\u00f5es no YouTrack, al\u00e9m de relatar novos issues se algo n\u00e3o funcionar para voc\u00ea. Compartilhe suas constata\u00e7\u00f5es sobre como os novos recursos atendem aos casos de uso nos seus projetos!<\/p>\n<p>Leituras e discuss\u00f5es adicionais:<\/p>\n<ul>\n<li><a href=\"https:\/\/kotlinlang.org\/docs\/reference\/whatsnew1430.html\" target=\"_blank\" rel=\"noopener\">P\u00e1gina de documenta\u00e7\u00e3o &#8220;Novidades&#8221;<\/a>.<\/li>\n<li><a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/inline-classes.md\" target=\"_blank\" rel=\"noopener\">Classes inline &#8211; KEEP<\/a>; discuss\u00e3o: <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\">Documento de design de classes value<\/a>; discuss\u00e3o no <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\">Registros JVM &#8211; KEEP<\/a>; discuss\u00e3o: <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\">Interfaces sealed e classes sealed &#8211; KEEP<\/a>; discuss\u00e3o: <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KT-42433\" target=\"_blank\" rel=\"noopener\">KT-42433<\/a>.<\/li>\n<\/ul>\n","protected":false},"author":1086,"featured_media":113696,"comment_status":"closed","ping_status":"closed","template":"","categories":[907],"tags":[91,477],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin\/121427"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/types\/kotlin"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/users\/1086"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/comments?post=121427"}],"version-history":[{"count":1,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin\/121427\/revisions"}],"predecessor-version":[{"id":121428,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/kotlin\/121427\/revisions\/121428"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media\/113696"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media?parent=121427"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/categories?post=121427"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/tags?post=121427"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/cross-post-tag?post=121427"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}