2017-08-13 2 views
3

J'essaie de comprendre en remplaçant une fonction de classe existante, avec une fonction d'extension de la même signature - prendra effet?Kotlin: Lorsque la fonction d'extension masque l'implémentation par défaut de la classe?

Voici mon exemple de code:

fun String.toUpperCase(): String = "ext. function impl." 

fun main(args: Array<String>) { 

    println("Hello".toUpperCase()) // ext. function impl. 

    println(MyClass().toUpperCase()) // class impl. 

} 

class MyClass { 
    fun toUpperCase() : String { 
     return "class impl." 
    } 
} 

fun MyClass.toUpperCase() : String { 
    return "ext. function impl." 
} 

Alors:

  • Quelles sont les règles? quand chacun sera appelé?
  • Comment puis-je remplacer cette décision? c'est possible?

Répondre

3

De the Kotlin docs (accent pas mien):

Si une classe a une fonction de membre, et une fonction d'extension est définie qui a le même type de récepteur, le même nom et est applicable à étant donné les arguments, le membre gagne toujours.

La raison pour laquelle votre exemple de chaîne fonctionne est parce que la bibliothèque fournie String.toUpperCase() est déjà une fonction d'extension, et non une fonction membre. Les docs n'indiquent pas ce qui se passe ici, mais il semble raisonnable de supposer qu'une extension locale gagne.


Je ne pense pas qu'il existe un moyen de modifier ce comportement. Et c'est probablement pour le mieux, car cela violerait le principe du moindre étonnement dans de nombreux cas (c'est-à-dire un comportement difficile à comprendre).

+1

Ce comportement est en fait modifié à quelques endroits dans 'kotlin-stdlib' (par exemple [ici] (https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/generated/_Maps. kt # L133)), mais cela est fait avec 'kotlin.internal.HidesMembers', qui est, évidemment, un outil interne et n'est pas disponible pour le code tiers. Et c'est pour de bon. – hotkey