web-dev-qa-db-fra.com

Kotlin: Comment créer une fonction héritable "statique"?

Par exemple, je veux avoir une fonction example() sur un type Child qui étend Parent afin que je puisse utiliser la fonction sur les deux.

Child.example()
Parent.example()

La première méthode "évidente" consiste à utiliser l'objet compagnon de Parent, mais cela ne permet pas à example() de Child.

La deuxième façon que j'ai essayée consistait à définir une fonction d'extension sur Parent.Companion, ce qui est peu pratique car vous êtes obligé de définir un objet compagnon. Il n'autorise pas non plus example() pour Child.

Est-ce que quelqu'un sait comment je peux faire ça?

17
Jire

Ce que vous demandez n'existe pas, vous semblez demander:

Puis-je référencer une méthode d'objet compagnon d'une super-classe à partir d'une référence de classe de ses descendants

ou peut-être vous demandez:

Puis-je référencer un membre statique d'une super-classe à partir d'une référence de ses descendants.

La réponse pour les deux est no. C’est à dessein de Kotlin que cela soit interdit, était une décision consciente, était intentionnelle. Si vous souhaitez modifier cette décision, vous devez signaler un problème dans YouTrack . Les programmeurs en Java étaient fortement confus par l'héritage et le dépassement des méthodes statiques et par le comportement lorsqu'ils sont appelés depuis une référence par rapport à une autre et par la façon dont ils sont résolus statiquement plutôt que dynamiquement. L’équipe Java 8, lorsqu’elle ajoute des méthodes statiques aux interfaces, réalise la confusion que cela pourrait causer et a donc opté pour une approche plus Kotlin consistant à ne lui permettre d’être appelée que par la référence d’interface. Pour éviter ces types de cauchemars, l'équipe de Kotlin l'a interdit. Tout comme ils ont refusé de nombreux autres aspects déroutants de Java.

Les autres réponses (@ voddan, par exemple) vous donnent la possibilité d’utiliser la même syntaxe d’appel en utilisant objets compagnon mais vous les refusez dans vos commentaires en vous disant que vous voulez éviter un objet compagnon. même si votre question indique que vous essayez de les utiliser. En supposant que vous ne souhaitiez pas les utiliser, la réponse est simplement non, cela ne peut pas être fait

Pour vous débarrasser de l'objet compagnon, vous voudrez parler de les fonctions d'extension peuvent-elles être appelées de manière «statique»? } ... ce qui sera décevant, car il n'est pas encore autorisé.

Pour revenir aux objets compagnon (désolé, mais ils sont le seul chemin d'accès à la gloire), vous pouvez également simplement déléguer manuellement la méthode de l'enfant au parent:

open class Parent {
    companion object { // required, sorry, no way around it!
        fun foo() = /* some cool logic here */
    }
}

class Child: Parent() {
    companion object {  // required, sorry, no way around it!
        fun foo() = Parent.foo() 
    }
}

Ou comme des extensions:

open class Parent {
    companion object {} // required, sorry, no way around it!
}

class Child: Parent() {
    companion object {} // required, sorry, no way around it!
}

fun Parent.Companion.foo() = /* some cool logic here */
fun Child.Companion.foo() = Parent.foo()
20
Jayson Minard

Comme les objets compagnons respectent les mêmes règles que tous les autres, il est facile d’utiliser des moyens normaux de réutilisation du code:

open class Example {
    fun example() {}
}

class Parent {
    companion object : Example()
}

class Child {
    companion object : Example()
}

fun main(args: Array<String>) {
    Child.example()
    Parent.example()
}

Alternativement, avec la délégation de classe, vous pouvez réutiliser directement l’implémentation de Parent:

interface Example {
    fun example()
}

class Parent {
    companion object : Example {
        override fun example() {}
    }
}

class Child {
    companion object : Example by Parent.Companion
}
11
voddan

Le but est de créer un "opérateur alternatif" à la construction

En Java, vous devez utiliser une Factory au lieu d’une méthode statique lorsqu’il est utilisé comme "constructeur".

Du côté de Kotlin, vous pouvez utiliser une fonction de niveau supérieur au lieu d’une usine.

Ou si vous voulez vraiment avoir une "méthode statique" dans votre classe, Je créerais un objet compagnon et ajouterais des méthodes d'extension statique.

0
D3xter