Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

441
Visualizações
Funciones de extensión de Kotlin: ¿diferencia entre Any? y genérico T?

Estaba programando por diversión y me preguntaba cuál debería usar. Probé los dos y me dieron el mismo resultado. Entonces, ¿cuál es la diferencia entre los dos?

Ejemplos:

 fun Any?.foo() = this != null fun <T> T?.foo() = this != null

La función real es un poco más complicada y en realidad hace algo basado en el tipo real del objeto (como un when con algunas opciones)

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

La segunda función le brinda una oportunidad que no se usa en este caso particular: captura el tipo del receptor en el parámetro de tipo T , para que pueda usarlo en otro lugar de la firma, como en los tipos de parámetros o el valor devuelto. type, o en el cuerpo de la función.

Como ejemplo bastante sintético, una listOf(this, this) dentro de la segunda función se escribiría como List<T?> , conservando el conocimiento de que el tipo de elementos es el mismo que el tipo de receptor, mientras que la misma expresión en la primera función sería una List<Any?> .

La primera función no permite utilizar el tipo de receptor de forma genérica para almacenar elementos de este tipo, aceptar elementos adicionales del mismo tipo como parámetros o utilizar el tipo de receptor en el tipo de valor de retorno de la función, mientras que la segunda función permite todos los estos.

Estas funciones son equivalentes desde la perspectiva del tiempo de ejecución, ya que los genéricos se borran del código de bytes de JVM cuando se compila el código, por lo que no podrá determinar el tipo T en el tiempo de ejecución y actuar en función de él, a menos que convierta la función en un función inline con un parámetro de tipo reified .


Como caso especial muy importante, capturar el tipo de un sitio de llamada en un parámetro de tipo permite que una función de orden superior acepte otra función usando T en su firma. La biblioteca estándar tiene un conjunto de funciones de alcance ( run , apply , let , also ) que muestran la diferencia.

Supongamos que la firma de also usó genéricos y se veía así:

 fun Any?.also(block: (Any?) -> Unit): Any? { ... }

Se puede llamar a esta función en cualquier objeto, pero su firma no muestra que es el objeto receptor el que se pasa al block y se devuelve desde la función; el compilador no podrá garantizar la seguridad de tipos y, por ejemplo, permitir una llamada a un miembro del objeto receptor sin verificación de tipo:

 val s: String = "abc" // won't compile: `it` is typed as `Any?`, the returned value is `Any?`, too val ss1: String = (s + s).also { println(it.length) } // this will work, but it's too noisy val ss2: String = (s + s).also { println((it as String).length) } as String

Ahora, capturar el parámetro de tipo es exactamente la forma de mostrar que es el mismo tipo en los tres lugares. Modificamos la firma de la siguiente manera:

 fun <T : Any?> T.also(block: (T) -> Unit): T { ... }

Y el compilador ahora puede inferir los tipos, sabiendo que es el mismo tipo T en todas partes donde aparece:

 val s: String = "abc" // OK! val ss: String = (s + s).also { println(it.length) }
over 4 years ago · Santiago Trujillo Relatório

0

Si ejecuta esto en la JVM, obtendrá lo siguiente

java.lang.ClassFormatError: nombre y firma del método duplicado en el archivo de clase...

Esto es interesante, por lo que desde el punto de vista de la firma son idénticos.

Depende en gran medida de su caso de uso, pero en la mayoría de los casos es posible que desee utilizar la variante genérica, ya que el tipo puede ser variable pero fijo en tiempo de compilación. Esta ventaja se vuelve obvia aquí:

 fun Any?.foo() = this fun <T> T?.bar() = this fun main(args: Array<String>) { val x = 5.foo() // Any? val y = 5.bar() // Int? }

Todas las propiedades y funciones disponibles en Int? no se podrá usar para x hasta que lo emita explícitamente (¿to e Int? ). y por otro lado "sabe" que devolvió un Int? .


En su ejemplo, no haría una diferencia ya que siempre devolverá un Boolean y, como ya se mostró, la firma es la misma.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda