Sök…


Anpassade operatörer

Swift stöder skapandet av anpassade operatörer. Nya operatörer deklareras på global nivå med hjälp av operator nyckelord.

Operatörens struktur definieras av tre delar: operandplacering, företräde och associativitet.

  1. prefix , infix och postfix används för att starta en anpassad operatörsdeklaration. postfix prefix och postfix anger huruvida operatören måste vara respektive före eller efter det värde som den verkar på. Sådana operatörer är urnary, som 8 och 3++ ** , eftersom de bara kan agera på ett mål. infix deklarerar en binär operatör som verkar på de två värdena den är mellan, till exempel 2+3 .

  2. Operatörer med högre prioritet beräknas först. Standardoperatörens företräde är bara högre än ? ... : (ett värde på 100 i Swift 2.x). Företräde för vanliga Swift-operatörer kan hittas här .

  3. Associativity definierar ordningen på operationer mellan operatörer med samma prioritet. Vänsterassosierande operatörer beräknas från vänster till höger (läsordning, som de flesta operatörer), medan högerassocierande operatörer beräknar från höger till vänster.

3,0

Från och med Swift 3.0 skulle man definiera företräde och associativitet i en prioritetsgrupp istället för själva operatören, så att flera operatörer enkelt kan dela samma företräde utan att hänvisa till de kryptiska siffrorna. Listan över standardprioritetsgrupper visas nedan .

Operatörer returnerar värden baserade på beräkningskoden. Denna kod fungerar som en normal funktion, med parametrar som anger vilken typ av ingång och return nyckelordet specificerar det beräknade värdet som operatören avkastning.

Här är definitionen av en enkel exponentiell operatör, eftersom standard Swift inte har en exponentiell operatör.

import Foundation    

infix operator ** { associativity left precedence 170 }

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

infix säger att ** operatören arbetar mellan två värden, till exempel 9**2 . Eftersom funktionen har lämnat associativitet beräknas 3**3**2 som (3**3)**2 . Förekomsten av 170 är högre än alla vanliga Swift-operationer, vilket betyder att 3+2**4 beräknar till 19 , trots den vänstra associativiteten ** .

3,0
import Foundation 

infix operator **: BitwiseShiftPrecedence

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

Istället för att specificera precedensen och associativiteten uttryckligen, på Swift 3.0 kan vi använda den inbyggda företrädesgruppen BitwiseShiftPrecedence som ger rätt värden (samma som << , >> ).

**: Ökning och minskning avskrivs och tas bort i Swift 3.

Överbelastning + för ordböcker

Eftersom det för närvarande inte finns något enkelt sätt att kombinera ordböcker i Swift, kan det vara användbart att överbelasta operatörerna + och += för att lägga till denna funktionalitet med hjälp av generik .

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

Från och med Swift 3 bör inout placeras före argumenttypen.

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

Exempel på användning:

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

Kommutativa operatörer

Låt oss lägga till en anpassad operatör för att multiplicera en CGS-storlek

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

Nu fungerar det

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

Men om vi försöker göra operationen omvänd, får vi ett fel

let sizeC = sizeB * 20          // ERROR

Men det är enkelt att lägga till:

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

Nu är operatören kommutativ.

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

Bitvisa operatörer

Snabba bitvisa operatörer låter dig utföra operationer i binär form av siffror. Du kan ange en binär bokstavskod genom att prefixera siffran med 0b , så till exempel 0b110 motsvarar det binära numret 110 (decimaltalet 6). Varje 1 eller 0 är lite i siffran.

Bitvis INTE ~ :

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

Här förändras varje bit till motsatsen. Att ange antalet som uttryckligen UInt8 säkerställer att antalet är positivt (så att vi inte behöver ta itu med negativa i exemplet) och att det bara är 8 bitar. Om 0b01101100 var ett större användargränssnitt, skulle det finnas ledande 0: er som skulle omvandlas till 1s och bli betydande vid 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

Bitvis OCH & :

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

Här kommer en given bit att vara 1 om och bara om de binära siffrorna på båda sidor om & operatören innehöll en 1 på den bitpositionen.

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

Bitvis ELLER | :

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

Här kommer en given bit att vara 1 om och bara om det binära talet på minst en sida av | operatören innehöll en 1 på den bitplatsen.

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

Bitvis XOR (exklusiv ELLER) ^ :

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

Här kommer en given bit att vara 1 om och bara om bitarna i den positionen för de två operandema är olika.

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

För alla binära operationer gör operandens ordning ingen skillnad på resultatet.

Överflödesoperatörer

Överflöde hänvisar till vad som händer när en operation skulle resultera i ett nummer som är antingen större eller mindre än det angivna antalet bitar för det numret kan innehålla.

På grund av hur binär aritmetik fungerar, efter att ett nummer blir för stort för sina bitar, flyter antalet ner till minsta möjliga antal (för bitstorleken) och fortsätter sedan att räkna upp därifrån. På samma sätt, när ett nummer blir för litet, flödar det upp till det största möjliga antalet (för sin bitstorlek) och fortsätter att räkna ner därifrån.

Eftersom detta beteende inte ofta önskas och kan leda till allvarliga säkerhetsproblem, kommer de snabba aritmetiska operatörerna + , - och * att kasta fel när en operation skulle orsaka ett överflöde eller underflöde. För att uttryckligen tillåta överflöde och underflöde, använd &+ , &- och &* istället.

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

Företräde för vanliga Swift-operatörer

Operatörer som bundit hårdare (högre prioritet) listas först.

operatörer Företrädesgrupp (≥3,0) Företräde associativitet
. vänster
? , ! , ++ , -- , [] , () , {} (Postfix)
! , ~ , + , - , ++ , -- (prefix)
~> (snabb ≤2,3) 255 vänster
<< , >> BitwiseShiftPrecedence 160 ingen
* , / , % , & , &* MultiplicationPrecedence 150 vänster
+ , - , | , ^ , &+ , &- AdditionPrecedence 140 vänster
... , ..< RangeFormationPrecedence 135 ingen
is , as , as? , as! CastingPrecedence 132 vänster
?? NilCoalescingPrecedence 131 rätt
< , <= , > , >= , == === != , === !== , ~= ComparisonPrecedence 130 ingen
&& LogicalConjunctionPrecedence 120 vänster
|| LogicalDisjunctionPrecedence 110 vänster
DefaultPrecedence * ingen
? ... : TernaryPrecedence 100 rätt
= , += , -= , *= , /= , %= , <<= , >>= , &= , |= , ^= AssignmentPrecedence 90 rätt, uppdrag
-> FunctionArrowPrecedence rätt
3,0
  • DefaultPrecedence företrädesgruppen är högre än TernaryPrecedence , men är inte ordnad med resten av operatörerna. Utöver denna grupp är resten av föregångarna linjära.


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow