Recherche…


Opérateurs personnalisés

Swift prend en charge la création d'opérateurs personnalisés. Les nouveaux opérateurs sont déclarés au niveau global en utilisant le mot-clé operator .

La structure de l'opérateur est définie en trois parties: placement de l'opérande, priorité et associativité.

  1. Les modificateurs de prefix , infix et postfix sont utilisés pour lancer une déclaration d'opérateur personnalisée. Les modificateurs de prefix et de postfix déclarent si l'opérateur doit être avant ou après, respectivement, la valeur sur laquelle il agit. Ces opérateurs sont urinaires, comme 8 et 3++ ** , car ils ne peuvent agir que sur une seule cible. L' infix déclare un opérateur binaire, qui agit sur les deux valeurs entre lesquelles il se trouve, telles que 2+3 .

  2. Les opérateurs avec une priorité supérieure sont calculés en premier. La priorité de l'opérateur par défaut est juste supérieure à ? ... : (une valeur de 100 dans Swift 2.x). La priorité des opérateurs Swift standard peut être trouvée ici .

  3. L'associativité définit l'ordre des opérations entre opérateurs de même priorité. Les opérateurs associatifs de gauche sont calculés de gauche à droite (ordre de lecture, comme la plupart des opérateurs), tandis que les opérateurs associatifs de droite calculent de droite à gauche.

3.0

À partir de Swift 3.0, on définirait la priorité et l’associativité dans un groupe de priorité au lieu de l’opérateur lui-même, de sorte que plusieurs opérateurs puissent facilement partager la même priorité sans faire référence aux nombres cryptés. La liste des groupes de priorité standard est indiquée ci - dessous .

Les opérateurs renvoient des valeurs en fonction du code de calcul. Ce code agit comme une fonction normale, avec des paramètres spécifiant le type d'entrée et le mot-clé de return spécifiant la valeur calculée que l'opérateur retourne.

Voici la définition d'un opérateur exponentiel simple, car Swift standard n'a pas d'opérateur exponentiel.

import Foundation    

infix operator ** { associativity left precedence 170 }

func ** (num: Double, power: Double) -> Double{
    return pow(num, power)
}

L' infix indique que l'opérateur ** travaille entre deux valeurs, telles que 9**2 . Comme la fonction a laissé une associativité, 3**3**2 est calculé comme suit: (3**3)**2 . La priorité de 170 est supérieure à toutes les opérations Swift standard, ce qui signifie que 3+2**4 calcule à 19 , malgré l’associativité de gauche de ** .

3.0
import Foundation 

infix operator **: BitwiseShiftPrecedence

func ** (num: Double, power: Double) -> Double {
    return pow(num, power)
}

Au lieu de spécifier explicitement la préséance et l'associativité, sur Swift 3.0, nous pourrions utiliser le groupe de priorité intégré BitwiseShiftPrecedence qui donne les valeurs correctes (identiques à << , >> ).

**: L'incrémentation et la décrémentation sont obsolètes et seront supprimées dans Swift 3.

Surcharge + pour les dictionnaires

Comme il n'existe actuellement aucun moyen simple de combiner des dictionnaires dans Swift, il peut être utile de surcharger les opérateurs + et += pour ajouter cette fonctionnalité à l'aide de génériques .

// Combines two dictionaries together. If both dictionaries contain
// the same key, the value of the right hand side dictionary is used.
func +<K, V>(lhs: [K : V], rhs: [K : V]) -> [K : V] {
    var combined = lhs
    for (key, value) in rhs {
        combined[key] = value
    }
    return combined
}

// The mutable variant of the + overload, allowing a dictionary
// to be appended to 'in-place'.
func +=<K, V>(inout lhs: [K : V], rhs: [K : V]) {
    for (key, value) in rhs {
        lhs[key] = value
    }
}
3.0

À partir de Swift 3, inout doit être placé avant le type d'argument.

func +=<K, V>(lhs: inout [K : V], rhs: [K : V]) { ... } 

Exemple d'utilisation:

let firstDict = ["hello" : "world"]
let secondDict = ["world" : "hello"]
var thirdDict = firstDict + secondDict // ["hello": "world", "world": "hello"]

thirdDict += ["hello":"bar", "baz":"qux"] // ["hello": "bar", "baz": "qux", "world": "hello"]

Opérateurs de communication

Ajoutons un opérateur personnalisé pour multiplier un CGSize

func *(lhs: CGFloat, rhs: CGSize) -> CGSize{
    let height = lhs*rhs.height
    let width = lhs*rhs.width
    return CGSize(width: width, height: height)
}

Maintenant cela fonctionne

let sizeA = CGSize(height:100, width:200)    
let sizeB = 1.1 * sizeA         //=> (height: 110, width: 220)

Mais si nous essayons de faire l'opération en sens inverse, nous obtenons une erreur

let sizeC = sizeB * 20          // ERROR

Mais c'est assez simple d'ajouter:

func *(lhs: CGSize, rhs: CGFloat) -> CGSize{
    return rhs*lhs
}

Maintenant, l'opérateur est commutatif.

let sizeA = CGSize(height:100, width:200)    
let sizeB = sizeA * 1.1              //=> (height: 110, width: 220)

Opérateurs sur les bits

Les opérateurs Swift Bitwise vous permettent d'effectuer des opérations sur la forme binaire des nombres. Vous pouvez spécifier un littéral binaire en préfixant le nombre avec 0b . Par exemple, 0b110 équivaut au nombre binaire 110 (nombre décimal 6). Chaque 1 ou 0 est un peu dans le nombre.

Bitwise NOT ~ :

var number: UInt8 = 0b01101100
let newNumber = ~number
// newNumber is equal to 0b01101100

Ici, chaque bit se transforme en son contraire. Déclarer explicitement le nombre UInt8 garantit que le nombre est positif (pour que nous n'ayons pas à traiter de négatifs dans l'exemple) et qu'il ne s'agisse que de 8 bits. Si 0b01101100 était un UInt plus grand, il y aurait des 0 qui seraient convertis en 1 et deviendraient significatifs lors de l'inversion:

var number: UInt16 = 0b01101100
// number equals 0b0000000001101100
// the 0s are not significant
let newNumber = ~number
// newNumber equals 0b1111111110010011
// the 1s are now significant
  • 0 à> 1
  • 1 -> 0

Bitwise AND & :

var number = 0b0110
let newNumber = number & 0b1010
// newNumber is equal to 0b0010

Ici, un bit donné sera 1 si et seulement si les nombres binaires des deux côtés de l'opérateur & contenaient un 1 à cet endroit du bit.

  • 0 & 0 -> 0
  • 0 & 1 -> 0
  • 1 & 1 -> 1

Bit à bit OU | :

var number = 0b0110
let newNumber = number | 0b1000
// newNumber is equal to 0b1110

Ici, un bit donné sera 1 si et seulement si le nombre binaire sur au moins un côté du | l'opérateur contenait un 1 à cet endroit du bit.

  • 0 | 0 -> 0
  • 0 | 1 -> 1
  • 1 | 1 -> 1

Bit à bit XOR (OU exclusif) ^ :

var number = 0b0110
let newNumber = number ^ 0b1010
// newNumber is equal to 0b1100

Ici, un bit donné sera 1 si et seulement si les bits dans cette position des deux opérandes sont différents.

  • 0 ^ 0 -> 0
  • 0 ^ 1 -> 1
  • 1 ^ 1 -> 0

Pour toutes les opérations binaires, l'ordre des opérandes ne fait aucune différence sur le résultat.

Opérateurs de débordement

Le dépassement de capacité se rapporte à ce qui se produit lorsqu'une opération aboutit à un nombre supérieur ou inférieur à la quantité de bits spécifiée pour ce numéro.

En raison de la façon dont fonctionne l'arithmétique binaire, après qu'un nombre soit devenu trop grand pour ses bits, le nombre déborde jusqu'au plus petit nombre possible (pour la taille du bit) et continue ensuite à compter. De la même manière, lorsqu'un nombre devient trop petit, il débouche sur le plus grand nombre possible (pour sa taille en bits) et continue à décompter à partir de là.

Étant donné que ce comportement n'est pas souvent souhaité et peut entraîner de graves problèmes de sécurité, les opérateurs arithmétiques Swift + , - et * émet des erreurs lorsqu'une opération provoque un débordement ou un débordement. Pour autoriser explicitement le dépassement et le sous-dépassement, utilisez plutôt &+ , &- et &* .

var almostTooLarge = Int.max
almostTooLarge + 1 // not allowed
almostTooLarge &+ 1 // allowed, but result will be the value of Int.min

Préséance des opérateurs Swift standard

Les opérateurs liés plus fortement (priorité supérieure) sont listés en premier.

Les opérateurs Groupe de préséance (≥3.0) Priorité Associativité
. la gauche
? , ! , ++ , -- , [] , () , {} (postfix)
! , ~ , + , - , ++ , -- (préfixe)
~> (swift ≤2.3) 255 la gauche
<< , >> BitwiseShiftPrecedence 160 aucun
* , / , % , & , &* MultiplicationPrecedence 150 la gauche
+ , - , | , ^ , &+ , &- AdditionPrecedence 140 la gauche
... , ..< RangeFormationPrecedence 135 aucun
is , as , as? , as! CastingPrecedence 132 la gauche
?? NilCoalescingPrecedence 131 droite
< , <= , > , >= , == != , === !== , ~= ComparaisonPrécédence 130 aucun
&& LogicalConjunctionPrecedence 120 la gauche
|| LogicalDisjunctionPrecedence 110 la gauche
DefaultPrecedence * aucun
? ... : TernaryPrecedence 100 droite
= , += , -= , *= , /= , %= , <<= , >>= , &= , |= , ^= AssignmentPrecedence 90 droit, cession
-> FunctionArrowPrecedence droite
3.0
  • Le groupe de priorité DefaultPrecedence est supérieur à TernaryPrecedence , mais il n'est pas ordonné avec le reste des opérateurs. Outre ce groupe, les autres priorités sont linéaires.


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow