Suche…


Benutzerdefinierte Operatoren

Swift unterstützt die Erstellung von benutzerdefinierten Operatoren. Neue Operatoren werden auf globaler Ebene mit dem operator Schlüsselwort deklariert.

Die Struktur des Operators besteht aus drei Teilen: Platzierung der Operanden, Rangfolge und Assoziativität.

  1. Die Modifizierer prefix , infix und postfix werden verwendet, um eine benutzerdefinierte Operatordeklaration zu starten. Die prefix und postfix Modifizierer legen fest, ob der Operator vor oder nach dem Wert stehen muss, auf den er wirkt. Solche Operatoren sind unüblich, wie 8 und 3++ ** , da sie nur auf ein Ziel wirken können. Das infix deklariert einen binären Operator, der auf die zwei Werte wirkt, zwischen denen es sich befindet, z. B. 2+3 .

  2. Operatoren mit höherer Priorität werden zuerst berechnet. Die Standardpriorität des Operators ist nur höher als ? ... : (ein Wert von 100 in Swift 2.x). Die Rangfolge der Standard-Swift-Operatoren finden Sie hier .

  3. Assoziativität definiert die Reihenfolge der Operationen zwischen Operatoren mit demselben Vorrang. Linke assoziative Operatoren werden von links nach rechts berechnet (Lesereihenfolge wie die meisten Operatoren), während rechte assoziative Operatoren von rechts nach links berechnen.

3,0

Ab Swift 3.0 würde man den Vorrang und die Assoziativität in einer Vorranggruppe anstelle des Operators selbst definieren, so dass mehrere Operatoren den gleichen Vorrang haben können, ohne sich auf die kryptischen Zahlen zu beziehen. Die Liste der Standard-Prioritätsgruppen ist unten aufgeführt .

Operatoren geben Werte basierend auf dem Berechnungscode zurück. Dieser Code fungiert als normale Funktion mit Parametern, die den Eingabetyp angeben, und das return , das den berechneten Wert angibt, den der Operator zurückgibt.

Hier ist die Definition eines einfachen Exponentialoperators, da der Standard-Swift keinen Exponentialoperator hat.

import Foundation    

infix operator ** { associativity left precedence 170 }

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

Das infix besagt, dass der Operator ** zwischen zwei Werten arbeitet, z. B. 9**2 . Da die Funktion die Assoziativität verlassen hat, wird 3**3**2 als (3**3)**2 berechnet. Der Vorrang von 170 ist höher als bei allen Standard-Swift-Operationen, was bedeutet, dass 3+2**4 trotz der linken Assoziativität von ** bis 19 berechnet wird.

3,0
import Foundation 

infix operator **: BitwiseShiftPrecedence

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

Anstatt die Priorität und die Assoziativität explizit anzugeben, können wir in Swift 3.0 die integrierte Prioritätsgruppe BitwiseShiftPrecedence verwenden, die die korrekten Werte angibt (wie << , >> ).

**: Das Inkrement und das Dekrement sind veraltet und werden in Swift 3 entfernt.

Überladen von + für Wörterbücher

Da es in Swift derzeit keine einfache Möglichkeit gibt, Wörterbücher zu kombinieren, kann es hilfreich sein, die Operatoren + und += zu überladen , um diese Funktionalität mit Generics hinzuzufügen.

// 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

Ab Swift 3 sollte inout vor dem Argumenttyp stehen.

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

Verwendungsbeispiel:

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"]

Kommutative Operatoren

Fügen wir einen benutzerdefinierten Operator hinzu, um ein CGSize-Feld zu multiplizieren

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

Das funktioniert jetzt

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

Wenn wir versuchen, die Operation umgekehrt auszuführen, wird ein Fehler angezeigt

let sizeC = sizeB * 20          // ERROR

Aber es ist einfach genug hinzuzufügen:

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

Jetzt ist der Operator kommutativ.

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

Bitweise Operatoren

Swift Bitwise-Operatoren ermöglichen die Ausführung von Operationen in binärer Form von Zahlen. Sie können ein 0b angeben, indem Sie der Zahl 0b . 0b110 entspricht also der Binärzahl 110 (der Dezimalzahl 6). Jede 1 oder 0 ist ein Bit in der Nummer.

Bitweise NICHT ~ :

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

Hier wird jedes Bit in sein Gegenteil geändert. Durch die Deklaration der Zahl als explizit UInt8 sichergestellt, dass die Zahl positiv ist (damit wir uns in diesem Beispiel nicht mit Negativen befassen müssen) und dass diese nur 8 Bit beträgt. Wenn 0b01101100 ein größerer UInt wäre, gäbe es führende 0s, die in 1s umgewandelt würden und bei Inversion signifikant würden:

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

Bitweises AND & :

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

Hier ist ein gegebenes Bit genau dann 1, wenn die Binärzahlen auf beiden Seiten des Operators & eine 1 an dieser Bitposition enthalten.

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

Bitweises ODER | :

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

Hier ist ein gegebenes Bit genau dann 1, wenn sich die Binärzahl auf mindestens einer Seite von | Operator enthielt an dieser Bitposition eine 1.

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

Bitweises XOR (exklusives ODER) ^ :

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

Ein gegebenes Bit ist hier genau dann 1, wenn sich die Bits in dieser Position der beiden Operanden unterscheiden.

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

Bei allen binären Operationen hat die Reihenfolge der Operanden keinen Einfluss auf das Ergebnis.

Überlaufoperatoren

Überlauf bezieht sich auf das, was passiert, wenn eine Operation dazu führen würde, dass eine Zahl größer oder kleiner als die festgelegte Anzahl von Bits für diese Anzahl ist.

Aufgrund der Funktionsweise der Binärarithmetik läuft die Anzahl der Bits zu groß, sobald eine Zahl für ihre Bits zu groß wird (für die Bitgröße), und zählt von dort aus weiter. Wenn eine Zahl zu klein wird, läuft sie auf die größtmögliche Anzahl (für ihre Bitgröße) unter und läuft weiter abwärts.

Da dieses Verhalten nicht oft gewünscht wird und zu schwerwiegenden Sicherheitsproblemen führen kann, werden die Swift-Rechenoperatoren + , - und * Fehler auslösen, wenn ein Vorgang einen Überlauf oder Unterlauf verursacht. Um Überlauf und Unterlauf explizit zuzulassen, verwenden Sie stattdessen &+ , &- und &* .

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

Vorrang vor Standard-Swift-Operatoren

Operatoren, die enger gebunden sind (höhere Priorität), werden zuerst aufgeführt.

Operatoren Vorranggruppe (≥ 3,0) Vorrang Assoziativität
. links
? ! , ++ , -- , [] , () , {} (postfix)
! , ~ , + , - , ++ , -- (Präfix)
~> (schnell ≤2,3) 255 links
<< , >> BitwiseShiftPrecedence 160 keiner
* , / , % , & , &* Multiplikationsvoraussetzung 150 links
+ , - , | , ^ , &+ , &- AdditionPrecedence 140 links
... , ..< RangeFormationPrecedence 135 keiner
is as as? as! CastingPrecedence 132 links
?? NilCoalescingPrecedence 131 Recht
< , <= , > , >= , == === != , === !== , ~= Vergleichspräferenz 130 keiner
&& LogicalConjunctionPrecedence 120 links
|| LogicalDisjunctionPrecedence 110 links
DefaultPrecedence * keiner
? ... : Ternäre Vorherrschaft 100 Recht
= , += , -= , *= , /= , %= , <<= , >>= , &= , |= , ^= AssignmentPrecedence 90 Richtig, Zuordnung
-> FunctionArrowPrecedence Recht
3,0
  • Die DefaultPrecedence ist höher als TernaryPrecedence , ist jedoch bei den übrigen Operatoren ungeordnet. Abgesehen von dieser Gruppe sind die übrigen Prioritäten linear.


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow