Extensión de Kotlin Any? .toString ()

He estado tratando de usar funciones de extensión en Kotlin.

class ExtensionExample() { var name: String? = null fun Any?.toString() : String { if (this == null) { return "Value is null" } return "Value is not null" } } 

Cuando imprimo la variable de nombre como abajo

 println(ExtensionExample().name.toString()) 

Debería imprimir como

 Value is null 

Pero no se imprime como esperaba. Solo imprime null .

¿Alguien puede explicar por favor?

Las funciones de extensión tienen scopes . Es por eso que no es accesible fuera de la class ExtensionExample .

Por lo general, las funciones de extensión se definen como funciones de nivel superior. Es decir, tienden a pertenecer fuera de una class .

Su extensión toString se define dentro de ExtensionExample . Esto es posible , pero significa que solo está disponible en el scope de esta class, y esta class solamente .

Es probable que su método main sea ​​una function de nivel superior (y no un miembro de esa class), por lo que no tiene acceso a esta function de extensión.

Solo otros miembros pueden acceder a esta function de extensión:

 class ExtensionExample { var name: String? = null fun Any?.toString(): String { return if (this == null) "Value is null" else "Value is not null" } fun foo() { println(name.toString()) } } fun main(args: Array<String>) { ExtensionExample().foo() } 

imprime "Value is null"

¡Pruébalo en línea!

La razón por la que se comstack es que el método toString que se está llamando es el método Any?.toString del kotlin-stdlib . Es decir, este método ya existe .

fun Any?.toString(): String

Devuelve una representación de cadena del object. Se puede invocar con un receptor nulo, en cuyo caso devuelve la cadena "nulo".

Mueva su function de extensión fuera de la class . Su function de extensión ocultará la extensión de stdlib y cualquier invocación en el mismo package que no importe explícitamente kotlin.toString utilizará su function.

Aquí hay una versión de trabajo de su código :

 class ExtensionExample { var name: String? = null } fun Any?.toString(): String { return if (this == null) "Value is null" else "Value is not null" } fun main(args: Array<String>) { println(ExtensionExample().name.toString()) } 

imprime "Value is null" , como quería.

¡Pruébalo en línea!


Tenga en count que no puede ocultar una function de miembro utilizando una function de extensión. Es decir,

 class Test { fun a() { println("a") } } fun Test.a() { println("b") } ... Test().a() 

dará como resultado que se imprima "a".

La única razón por la cual funciona Any?.toString (después de haber sido movido fuera de la class) es Any? no tiene miembros, ya que no es una class, sino un tipo anulable con la class Any . El método toString ya existente también es una extensión, por lo que el tuyo no está oculto por ningún miembro.

Definir una function de extensión dentro de una class:

Si desea dejar la definición de toString() dentro de ExtensionExample , solo puede usarla desde allí:

 class ExtensionExample() { var name: String? = null // uses the toString() extension function defined in ExtensionExample fun useToString() = name.toString() fun Any?.toString(): String { if (this == null) { return "inside: Value is null" } return "inside: Value is not null" } } 

Esta

 // uses the version of toString() defined in the Kotlin Standard library println(ExtensionExample().name.toString()) // uses the inside version of toString() println(ExtensionExample().useToString()) 

imprimirá

nulo
adentro: el valor es nulo

Definir una function de extensión fuera de una class:

Pero si quieres usarlo afuera, tienes que moverlo afuera:

 class ExtensionExample() { var name: String? = null // uses the toString() extension function defined in ExtensionExample fun useToString() = name.toString() fun Any?.toString(): String { if (this == null) { return "inside: Value is null" } return "inside: Value is not null" } } fun Any?.toString(): String { if (this == null) { return "outside: Value is null" } return "outside: Value is not null" } 

Esta

 // uses the outside version of toString() which overrides the one from the Kotlin Standard library println(ExtensionExample().name.toString()) // uses the inside version of toString() println(ExtensionExample().useToString()) 

se imprimirá:

afuera: el valor es nulo
adentro: el valor es nulo

Si una class tiene una function miembro, y se define una function de extensión que tiene el mismo tipo de receptor, el mismo nombre y es aplicable a arguments dados, el miembro siempre gana.

Su método de extensión no puede sombrear el método toString incorporado en la class Any ( Object ).

En cuanto a llamar a toString en un tipo anulable, este método ya está en el time de ejecución de Kotlin:

 /** * Returns a string representation of the object. Can be called with a null receiver, in which case * it returns the string "null". */ public fun Any?.toString(): String 

Ver también los documentos sobre la resolución de extensiones.

  • Kotlin || ¿No puedo agregar la biblioteca a Mi aplicación?
  • Convierta un ArrayMap en ArrayList - Kotlin
  • La function Kotlin requiere nada, pero se define como un tipo diferente
  • Android Kotlin .visibilidad
  • La extensión sintética de Kotlin y varias incluyen el mismo layout
  • Diálogo personalizado de Kotlin Parámetro especificado como no nulo
  • Clases de Kotlin sin llaves
  • kotlin jvmname ignorado por Gradle?
  • La anotación de ButterKnife @OnClick no funciona en el fragment de Kotlin
  • Imposible get datos de la database sqlite
  • Cómo pasar el nombre de db en time de ejecución en kotlin