Zoeken…


Aangepaste operatoren

Swift ondersteunt het maken van aangepaste operators. Nieuwe operators worden op mondiaal niveau gedeclareerd met behulp van het operator .

De structuur van de operator wordt bepaald door drie delen: operandplaatsing, prioriteit en associativiteit.

  1. De prefix , infix en postfix modificaties worden gebruikt om een aangepaste operatorverklaring te starten. De prefix en postfix modificatoren geven aan of de operator respectievelijk vóór of na de waarde moet staan waarop deze werkt. Dergelijke operatoren zijn urnary, zoals 8 en 3++ ** , omdat ze slechts op één doel kunnen reageren. De infix verklaart een binaire operator, die werkt op de twee waarden waartussen het ligt, zoals 2+3 .

  2. Operators met een hogere prioriteit worden eerst berekend. De standaard operatorprioriteit is gewoon hoger dan ? ... : (een waarde van 100 in Swift 2.x). De prioriteit van de standaard Swift operators kan worden gevonden hier .

  3. Associativiteit definieert de volgorde van bewerkingen tussen operatoren van dezelfde prioriteit. Linker associatieve operatoren worden van links naar rechts berekend (leesvolgorde, zoals de meeste operatoren), terwijl rechts associatieve operatoren van rechts naar links berekenen.

3.0

Beginnend met Swift 3.0 zou men de prioriteit en associativiteit in een prioriteitsgroep definiëren in plaats van de operator zelf, zodat meerdere operators gemakkelijk dezelfde prioriteit kunnen delen zonder naar de cryptische getallen te verwijzen. De lijst met standaard prioriteitsgroepen wordt hieronder weergegeven .

Operators retourneren waarden op basis van de berekeningscode. Deze code dient als een normale functie, met parameters die het soort ingangssignaal en het return sleutelwoord vermelding van de berekende waarde die de gebruiker terugkeert.

Hier is de definitie van een eenvoudige exponentiële operator, omdat standaard Swift geen exponentiële operator heeft.

import Foundation    

infix operator ** { associativity left precedence 170 }

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

De infix zegt dat de ** operator tussen twee waarden werkt, zoals 9**2 . Omdat de functie associativiteit heeft verlaten, wordt 3**3**2 berekend als (3**3)**2 . De prioriteit van 170 is hoger dan alle standaard Swift-bewerkingen, wat betekent dat 3+2**4 berekend wordt tot 19 , ondanks de linkse associativiteit van ** .

3.0
import Foundation 

infix operator **: BitwiseShiftPrecedence

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

In plaats van de prioriteit en associativiteit expliciet op te geven, zouden we op Swift 3.0 de ingebouwde prioriteitsgroep BitwiseShiftPrecedence kunnen gebruiken die de juiste waarden geeft (hetzelfde als << , >> ).

**: De toename en afname zijn verouderd en worden verwijderd in Swift 3.

Overbelasting + voor woordenboeken

Aangezien er momenteel geen eenvoudige manier is om woordenboeken in Swift te combineren, kan het handig zijn om de operatoren + en += te overbelasten om deze functionaliteit met behulp van generieke geneesmiddelen toe te voegen.

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

Vanaf Swift 3 moet inout vóór het argumenttype worden geplaatst.

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

Voorbeeld gebruik:

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

Commutatieve operators

Laten we een aangepaste operator toevoegen om een CGSize te vermenigvuldigen

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

Nu werkt dit

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

Maar als we proberen de bewerking in omgekeerde volgorde uit te voeren, krijgen we een foutmelding

let sizeC = sizeB * 20          // ERROR

Maar het is eenvoudig genoeg om toe te voegen:

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

Nu is de operator commutatief.

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

Bitwise Operators

Met snelle Bitwise-operatoren kunt u bewerkingen uitvoeren op de binaire vorm van getallen. U kunt een binaire letterlijke waarde opgeven door het getal vooraf te laten gaan door 0b , dus 0b110 is bijvoorbeeld gelijk aan het binaire getal 110 (het decimale getal 6). Elke 1 of 0 is een beetje in het nummer.

Bitwise NOT ~ :

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

Hier wordt elk bit veranderd in het tegenovergestelde. Het nummer expliciet UInt8 zorgt ervoor dat het nummer positief is (zodat we niet met negatieven in het voorbeeld te maken hebben) en dat het slechts 8 bits is. Als 0b01101100 een grotere UInt was, zouden er voorloopnullen zijn die worden geconverteerd naar en en significant worden bij inversie:

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

Hier is een gegeven bit 1 als en alleen als de binaire getallen aan beide zijden van de & operator een 1 bevatten op die bitlocatie.

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

Bitgewijs OF | :

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

Hier is een gegeven bit 1 als en alleen als het binaire getal aan ten minste één zijde van de | operator bevatte een 1 op die bitlocatie.

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

Bitwise XOR (exclusief OF) ^ :

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

Hier is een gegeven bit 1 als en alleen als de bits in die positie van de twee operanden verschillend zijn.

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

Voor alle binaire bewerkingen maakt de volgorde van de operanden geen verschil in het resultaat.

Overloopoperators

Overloop verwijst naar wat er gebeurt als een bewerking zou resulteren in een getal dat groter of kleiner is dan het toegewezen aantal bits voor dat nummer.

Vanwege de manier waarop binaire rekenkunde werkt, stroomt het nummer, nadat een getal te groot is geworden voor zijn bits, over naar het kleinst mogelijke getal (voor de bitgrootte) en gaat dan verder met tellen. Evenzo, wanneer een nummer te klein wordt, stroomt het naar het grootst mogelijke nummer (vanwege de bitgrootte) en blijft het aftellen vanaf daar.

Omdat dit gedrag niet vaak gewenst is en tot ernstige beveiligingsproblemen kan leiden, geven de rekenkundige operatoren Swift + , - en * fouten wanneer een bewerking een overloop of onderloop zou veroorzaken. Gebruik in plaats daarvan &+ , &- en &* om overloop en onderloop expliciet toe te staan.

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

Voorrang van standaard Swift-operators

Operatoren die strakker gebonden zijn (hogere prioriteit) worden eerst vermeld.

operators Voorrangsgroep (≥3.0) Voorrang associativiteit
. links
? , ! , ++ , -- , [] , () , {} (Postfix)
! , ~ , + , - , ++ , -- (voorvoegsel)
~> (snel ≤2.3) 255 links
<< , >> BitwiseShiftPrecedence 160 geen
* , / , % , & , &* MultiplicationPrecedence 150 links
+ , - , | , ^ , &+ , &- AdditionPrecedence 140 links
... , ..< RangeFormationPrecedence 135 geen
is , as , as? as! CastingPrecedence 132 links
?? NilCoalescingPrecedence 131 Rechtsaf
< , <= , > , >= , == != , === !== , ~= ComparisonPrecedence 130 geen
&& LogicalConjunctionPrecedence 120 links
|| LogicalDisjunctionPrecedence 110 links
DefaultPrecedence * geen
? ... : TernaryPrecedence 100 Rechtsaf
= , += , -= , *= , /= , %= , <<= , >>= , &= , |= , ^= AssignmentPrecedence 90 recht, opdracht
-> FunctionArrowPrecedence Rechtsaf
3.0
  • De standaardvoorrangsgroep DefaultPrecedence is hoger dan TernaryPrecedence , maar is niet geordend bij de rest van de operatoren. Anders dan deze groep, zijn de rest van de prioriteiten lineair.


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow