O código a seguir funciona como esperado em scala2, mas gera um erro em tempo de compilação em scala3. Tentei encontrar uma explicação em Programação em Scala, Quinta Edição e na web, mas não consegui. Alguma ideia?
object Main {
def main(args:Array[String]): Unit = {
val foo = new Foo(7)
println(foo.double) // 14
val bar = new Foo(8) {
def triple:Int = this.i * 3
}
println(bar.double) // 16
println(bar.triple) // 24 in scala2; compile error in scala3
}
}
class Foo(val i:Int) {
def double:Int = i*2
}
Erro de compilação:
-- [E008] Not Found Error: /tmp/example.scala:12:20 ----
12 | println(bar.triple)
| ^^^^^^^^^^
| value triple is not a member of Foo
Se você compilar seu código com
scala -Xprint:typer
, verá queval bar
agora tem explicitamente o tipoFoo
no Scala 3:Compare isso com Scala 2, onde
bar
obtém o tipo de refinamentoFoo { def triple: Int }
:Então, é
Para alcançar o comportamento do Scala 2, você poderia introduzir
Bar
explicitamente uma nova classe:Código compilável completo:
Quanto ao motivo pelo qual está inferindo
Foo
em vez deFoo { def triple: Int }
- não tenho certeza, acho que eles descobriram que esse comportamento funciona melhor com outros recursos da linguagem.Como você explicaria que
val x = "hello"
inferex: String
e nãox: "hello"
?Isso é abordado no guia de migração Scala 3 em https://docs.scala-lang.org/scala3/guides/migration/incompat-type-inference.html#reflective-type :