Dans le 14e Kotlin Koan sur la surcharge de l'opérateur, j'ai été surpris quand après la résolution j'ai vu la réponse et j'ai vu que le modificateur operator
n'était pas requis sur la méthode compareTo
:
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
override fun compareTo(other: MyDate) = when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
}
Le opérateur surchargeant les documents lié à de l'exercice dit explicitement:
Les fonctions qui surchargent les opérateurs doivent être marquées avec le modificateur d'opérateur.
Alors qu'est-ce qui se passe ici? Pourquoi ce code se compile-t-il? Quand est exactement operator
requis?
Pourquoi ce code se compile-t-il?
Cela se compile car la méthode d'interface remplacée, Comparable<T>.compareTo
, est un operator fun
.
/**
* Compares this object with the specified object for order. Returns zero if this object is equal
* to the specified [other] object, a negative number if it's less than [other], or a positive number
* if it's greater than [other].
*/
public operator fun compareTo(other: T): Int
Comme la fonction l'emporte, c'est aussi une fonction opérateur.
Quand est exactement
operator
requis?
operator
en général est requis chaque fois que vous souhaitez pouvoir utiliser une fonction comme s'il s'agissait d'un opérateur, car les opérateurs sont simplement compilés pour appeler des fonctions (sauf sur les types primitifs, etc.)
Autrement dit, foo += bar
, Par exemple, est équivalent à foo.plusAssign(bar)
, foo[bar] = baz
Est équivalent à foo.set(bar, baz)
, etc.
Personnellement, je préfère spécifier operator
dans la mesure du possible, même si ce n'est pas nécessaire, pour des raisons de lisibilité.
Si MyDate
n'était pas un Comparable
, et que vous avez omis le modificateur operator
, en comparant deux dates via <
, >
, <=
ou >=
ne seront pas compilés.
Cependant, je n'ai rien trouvé dans la spécification . Cependant, dans un sens polymorphe, cela a du sens - pourquoi devriez-vous être en mesure d'écrire a < b
Où le type de a
et b
sont des Comparable
, mais pas quand ils sont un MyDate
? Comme vous ne pourrez pas supprimer "l'opératrice" de cette fonction, il est logique que operator
soit héritable de la méthode de la superclasse.
Kotlin possède de nombreuses fonctionnalités qui sont activées via des conventions particulières . Ceux-ci peuvent être identifiés à l'aide d'un mot clé operator
. Les exemples sont plages, surcharges d'opérateur, opérateurs d'index, déclarations de déstructuration et plus .
Si nous voulons comparer deux objets en Java, pour le tri par exemple, nous implémentons l'interface Comparable
avec sa méthode compareTo
. Cela se fait également dans Kotlin, mais avec un bien meilleur support et une syntaxe abrégée. Si vous implémentez cette méthode dans une classe, vous pouvez utiliser tous les opérateurs Nice comme <
, <=
, >
, >=
Avec cette classe hors du boîte. Ces opérateurs sont traduits en appels appropriés de compareTo
par le compilateur:
obj1 > obj2
⇒ obj1.compareTo(obj2) > 0
La méthode d'interface compareTo
dans Comparable
définit déjà le mot clé operator
, ce qui rend redondant l'ajout du mot clé dans votre propre implémentation.
Dans votre exemple, le mot clé operator
n'est pas obligatoire car la méthode substituée le définit déjà.
En Java, les opérateurs sont liés à des types spécifiques Java. Par exemple, les types String et numériques dans Java peuvent utiliser l'opérateur + pour la concaténation et l'addition, respectivement). Aucun autre type Java ne peut réutiliser cet opérateur pour son propre bénéfice. Kotlin, au contraire, fournit un ensemble de conventions pour prendre en charge une surcharge d'opérateur limitée.
Commençons par une classe de données simple:
data class Point(val x: Int, val y: Int)
Nous allons améliorer cette classe de données avec quelques opérateurs.
Afin de transformer une fonction Kotlin avec un nom prédéfini en opérateur, nous devons marquer la fonction avec le modificateur d'opérateur. Par exemple, nous pouvons surcharger l'opérateur "+":
operator fun Point.plus(other: Point) = Point(x + other.x, y + other.y)
De cette façon, nous pouvons ajouter deux points avec "+":
val p1 = Point (0, 1)
val p2 = Point (1, 2)
println (p1 + p2)
Point (x = 1, y = 3)