Por favor, explique esse comportamento em Kotlin:
data class A<T>(val p: T)
class B
fun f1(): A<Number> = A(B()) as A<Number>
fun f2(): A<Unit> = A(B()) as A<Unit>
fun main() {
println("f1: ${f1().p::class.simpleName}") // print "f1: B"
println("f2: ${f2().p::class.simpleName}") // print "f2: Unit"
}
Eu esperaria a saída "B" tanto no primeiro quanto no segundo caso.
Além disso, curiosamente, ele funciona corretamente para data class A<T>(val p: T?)
.
É algum tipo de otimização do compilador?
Quando o tipo de retorno é declarado como
Unit
, o Kotlin aplica um comportamento específico, forçando o resultado aUnit
ignorar o valor de retorno real.Isso é declarado nas especificações do Kotlin: Coerção para kotlin.Unit .
Nesta linha
fun f2(): A<Unit> = A(B()) as A<Unit>
, é declarado que o tipo dep
deve serUnit
. Então, o Kotlin descarta o valor de retorno real def2().p
e força o valor de retorno paraUnit
.O mesmo comportamento se aplica a funções com um tipo de retorno explicitamente declarado de
Unit
Esse comportamento é frequentemente usado ao escrever testes JUnit , pois o JUnit não executa métodos de teste a menos que seu tipo de retorno seja
Unit
. Semelhante ao Java, onde o JUnit não executa métodos de teste a menos que seu tipo de retorno sejavoid
.Em relação ao caso
data class A<T>(val p: T?)
:o tipo de
p
estáUnit?
no caso deA(B()) as A<Unit>
, e acho que Kotlin distingue entreUnit
eUnit?
e, portanto, não aplica a lógica de coerção.