web-dev-qa-db-fra.com

Méthodes d'extension statique à Kotlin

Comment définissez-vous une méthode d'extension statique dans Kotlin? Est-ce seulement possible? J'ai actuellement une méthode d'extension comme indiqué ci-dessous.

public fun Uber.doMagic(context: Context) {
    // ...
}

L'extension ci-dessus peut être invoquée sur une instance.

uberInstance.doMagic(context) // Instance method

mais comment puis-je le faire méthode statique comme indiqué ci-dessous.

Uber.doMagic(context)         // Static or class method
120
Ragunath Jawahar

Pour obtenir Uber.doMagic(context), vous pouvez écrire une extension dans le objet compagnon de Uber (la déclaration de l'objet compagnon est requise):

class Uber {
    companion object {}
}

fun Uber.Companion.doMagic(context: Context) { }
112
Andrey Breslav

Voici ce que dit la documentation officielle:

Kotlin génère des méthodes statiques pour les fonctions au niveau du package. Kotlin peut également générer des méthodes statiques pour les fonctions définies dans des objets nommés ou des objets compagnons si vous annotez ces fonctions en tant que @JvmStatic. Par exemple:

méthodes statiques de Kotlin

class C {
  companion object {
    @JvmStatic fun foo() {}
    fun bar() {}
  }
}

Maintenant, foo () est statique en Java, alors que bar () n'est pas:

C.foo(); // works fine
C.bar(); // error: not a static method
9
lucasddaniel

Vous pouvez créer une méthode statique en utilisant un objet Companion comme:

class Foo {
    // ...
    companion object {
        public fun bar() {
            // do anything
        }
    }
}

et ensuite vous pouvez l'appeler comme ceci:

class Baz {
    // ...
    private fun callBar() {
        Foo.bar()
    }
}
5
bbarm

J'avais en fait cette question il y a 30 minutes. J'ai donc commencé à chercher et je ne trouvais aucune solution ni solution de contournement, MAIS lors de la recherche, j'ai trouvé cette section sur le site Web de Kotlinglang, qui indique que:

Notez que les extensions peuvent être définies avec un type de destinataire nullable. De telles extensions peuvent être appelées sur une variable d'objet même si sa valeur est null.

Alors, alors j'ai eu l'idée la plus folle de tous les temps, pourquoi ne pas définir une fonction d'extension avec un récepteur nullable (sans utiliser réellement ce récepteur) et l'appeler ensuite sur un objet nul! Alors j’ai essayé cela, et ça a plutôt bien fonctionné, mais c’était si moche. C'était comme ça:

(null as Type?).staticFunction(param1, param2)

J'ai donc contourné cela en créant un val dans mon fichier d'extensions du type récepteur qui avait la valeur null, puis je l'utilisais dans mon autre classe. Ainsi, à titre d'exemple, voici comment j'ai implémenté une fonction d'extension "statique" pour la classe Navigation sous Android: Dans mon fichier NavigationExtensions.kt:

val SNavigation: Navigation? = null
fun Navigation?.createNavigateOnClickListener(@IdRes resId: Int, args: Bundle? = null, navOptions: NavOptions? = null,
                                                navigationExtras: Navigator.Extras? = null) : (View) -> Unit {
    //This is just implementation details, don't worry too much about them, just focus on the Navigation? part in the method declaration
    return { view: View -> view.navigate(resId, args, navOptions, navigationExtras) }
}

Dans le code qui l'utilise:

SNavigation.createNavigateOnClickListener(R.id.action_gameWonFragment_to_gameFragment)

Évidemment, ce n'est pas un nom de classe, c'est juste une variable de type classe qui a une valeur nulle. C’est évidemment moche du côté du fabricant d’extensions (car ils doivent créer la variable) et du côté développeur (car ils doivent utiliser le format SType au lieu du nom de la classe), mais c’est le plus proche. cela peut être réalisé maintenant par rapport aux fonctions statiques réelles. Espérons que les créateurs de la langue Kotlin réagiront au numéro qui a été créé et ajouteront cette fonctionnalité dans la langue.

1
kyay

Je vous recommande de regarder this link. Comme vous pouvez le constater, vous devez déclarer une méthode au plus haut niveau du paquet (fichier):

package strings
public fun joinToString(...): String { ... }

C'est égal à

package strings;

public class JoinKt {
    public static String joinToString(...) { ... }
}

Avec les constantes, tout est pareil. Cette déclaration

val UNIX_LINE_SEPARATOR = "\n"

est égal à

public static final String UNIX_LINE_SEPARATOR = "\n";
0
Nisazh