[SWIFTプログラミング-5章]演算子


この文章はSWIFTプログラミング(3版、野熊の音)を読んで簡単にまとめたものです.本には親切な説明と関連するサンプルコードがあるので、自分で買って読むことをお勧めします.

5.0概要


swiftの演算子は、特定の文字で表される関数です.
演算子の演算値の数によって、単項、二項、三項などに分けられます.
  • 単項演算子:!A
  • 異項演算子:A+B
  • の3つの演算子:A?B : C
  • 演算子の位置によって、前列、中列、後列などに分けられます.
  • 電位演算子:!A
  • 中位数演算子:A+B
  • 接尾辞演算子:A!
  • *書き換えも重要な文法です.次の2つのコードには異なる意味があります.
    A != B // A와 B는 같지 않다
    A! = B // A의 강제 언래핑 값과 B는 같다

    5.1演算子のタイプ


    5.1.1割付演算子


    分配価格
    A = B // A에 B를 할당한다

    5.1.2算術演算子


    数学で使用される演算を実行します.
    A + B // A와 B를 더한다
    A - B // A에서 B를 뺀다
    A * B // A와 B를 곱한다
    A / B // A에서 B를 나눈 값을 반환한다
    A % B // A에서 B를 나눈 나머지를 반환한다
    浮動小数点タイプの残りの演算も可能です.
    let double: Double = 5.0
    let doubleResult: Double = double.truncatingRemainder(dividingBy: 1.5) // 0.5
    
    let int: Int = 5
    let intResult: Int = 5 / 2 // 2

    5.1.3比較演算子


    2つの値を比較し、不完全な値を返します.
    A == B // A와 B가 같다
    A != B // A와 B가 같지 않다
    
    A >= B // A가 B보다 크거나 같다
    A <= B // A가 B보다 작거나 같다
    A > B // A가 B보다 크다
    A < B // A가 B보다 작다
    
    A === B // A와 B가 참조타입일 때 같은 인스턴스를 가리킨다
    A !== B // A와 B가 참조타입일 때 다른 인스턴스를 가리킨다
    A ~= B // A와 B의 패턴이 매치되는지 확인한다
    参照比較演算子は、sweetの一意の参照タイプであるクラスのインスタンスでのみ使用できます.sweetのすべての基本データ型は構造体として実装されるため、値の比較演算子==が使用され、クラスのインスタンスである場合にのみ==が使用されます.
    let valueA: Int = 3
    let valueB: Int = 4
    
    let isSameValue = valueA == valueB // false
    class SomeClass {
        ...
    }
    
    let referenceA: SomeClass = SomeClass()
    let referenceB: SomeClass = SomeClass()
    let referenceC: SomeClass = referenceA
    
    let isSameReferenceAB = referenceA === referenceB // false
    let isSameReferenceAC = referenceA === referenceC // true

    5.1.4 3項条件演算子


    被演算子は3つあります.
    A == B ? 1 : 0 // A와 B가 같으면 1을, 아니면 0을 반환한다

    5.1.5範囲演算子


    値の範囲を表します.「≪クローズド|Closed|Planning≫」、「≪セミクローズド|セミクローズド|Planning≫」、「≪シングル・インバース範囲演算子|Single Invert Range Operator|Planning≫」の順に選択します.
    A...B // A 이상 B 이하의 범위이다
    A..<B // A 이상 B 미만의 범위이다
    A... // A 이상의 범위이다
    ...A // A 이하의 범위이다
    ..<A // A 미만의 범위이다

    5.1.6ブール演算子


    ブール値の論理演算を行います.
    !A // A 불리언을 반전한다
    A && B // A와 B를 만족한다
    A || B // A 또는 B를 만족한다

    5.1.7ビット演算子


    値のビット論理演算を行います.
    ~A // A의 비트를 반전한다
    A & B // A와 B의 비트 AND 논리 연산을 실행한다
    A | B // A와 B의 비트 OR 논리 연산을 실행한다
    A ^ B // A와 B의 비트 XOR 논리 연산을 실행한다
    A >> B // A의 비트를 왼쪽으로 B만큼 이동한다
    A << B // A의 비트를 오른쪽으로 B만큼 이동한다

    5.1.8複合割付演算子


    割り当て演算子と別の演算子を結合します.
    A += B // A와 B의 합을 A에 할당한다
    A -= B // A와 B의 차를 A에 할당한다
    A *= B // A와 B의 곱을 A에 할당한다
    A /= B // A와 B의 나눈 값을 A에 할당한다
    A %= B // A와 B의 나눈 나머지를 A에 할당한다
    
    A <<= N // A의 비트를 왼쪽으로 N만큼 이동한 값을 A에 할당한다
    A >>= N // A의 비트를 오른쪽으로 N만큼 이동한 값을 A에 할당한다
    A &= B // A와 B의 비트 AND 연산 결과를 A에 할당한다
    A != B // A와 B의 비트 OR 연산 결과를 A에 할당한다
    A ^= B // A와 B의 비트 XOR 연산 결과를 A에 할당한다

    5.1.9オーバーフロー演算子


    オーバーフロー処理UInt 8タイプは8ビット整数タイプで正の整数のみを表し、下向き0の計算を行うとランタイムエラーになります.したがって,オーバーフロー演算子を用いて処理を行う.
    let uInt: UInt8 = 0
    let errorResult: UInt8 = uInt - 1 // 런타임 에러 발생
    let underflowedResult: UInt8 = uInt &- 1 // 255

    5.1.10その他の演算子

    A ?? B // A가 nil이 아니면 A를, nil라면 B를 반환한다
    -A // A의 부호를 변경한다
    O! // 옵셔널 개체인 O를 강제 언래핑한다
    V? // 옵셔널 값인 V를 안전하게 추출한다. 또는 V의 데이터 타입이 옵셔널임을 표현한다.
    オプションのInt値はIntですか?タイプです.
    let valueInt: Int = optionalInt ?? 0

    5.2演算子の優先度と連結方向


    swiftは、演算子の優先度と連結方向を指定します.優先度の高い演算子は、最初に実行され、同じ優先度であれば、どの方向からグループ化を開始するかを示します.演算子の優先度は絶対値ではなく相対値です.
    1 + 2 + 3 == ((1 + 2) + 3)
    1 + 2 * 3 == (1 + (2 * 3))

    5.3カスタム演算子


    必要な演算子を定義できます.アスキー文字、/、=、-、+、!、*、%、<、>、&、|、^、?、~使用します.ピリオド(.)カスタム演算子として使用する場合は、先頭の文字は句点でなければなりません.
  • 接頭辞:親演算子
  • postfix:接尾辞演算子
  • infix:中位数演算子
  • 演算子:演算子
  • 相関:演算子結合方向
  • 優先順位
  • :優先順位
  • 5.3.1電位演算子の定義と実現


    Intタイプの平方と立方を計算する接尾辞演算子を作成します.
    prefix operator **
    prefix operator ***
    
    prefix func ** (value: Int) -> Int {
        return value * value
    }
    
    prefix func *** (value: Int) -> Int {
        return value * value * value
    }
    
    let sqrtFive: Int = **5 // 25
    let cubicFive: Int = ***5 // 125
    swift標準ライブラリに存在する演算子に機能を追加する場合は、演算子を個別に定義する必要はなく、関数を繰り返し定義するだけです.
    prefix func ! (value: String) -> Bool {
        return value.isEmpty
    }
    
    let string: String = ""
    let isEmptyString: Bool = !string // true
    また、以前に作成したユーザ電位演算子を繰り返し定義して、他のデータ型でも動作させることもできます.
    prefix operator **
    
    prefix func ** (value: String) -> String {
        return value + value
    }
    
    let sqrtString: String = **"hello" // hellohello

    5.3.2接尾辞演算子の定義と実施


    被演算子にプリアンブル演算とポストガイド演算がある場合は、まずポストガイド演算を実行します.
    prefix operator **
    postfix operator **
    
    prefix func ** (value: Int) -> Int {
        return value * value
    }
    
    postfix func ++ (value: Int) -> Int {
        return value + value
    }
    
    let result: Int = **5++ // ((5 + 5) * (5 + 5)) // 100

    5.3.3中位演算子の定義と実施


    上記の2つの演算子とは異なり、中位数演算子は優先度グループを指定できます.
  • 高erthan:優先度の低いグループ名を指定します.
  • LowerThan:より優先度の高いグループ名を指定します.
  • 関連性:結合方向(none,left,right)を示す.
  • タスク:オープン・フィルタに関連します.割り当て方向(true、false)を指定します.
  • infix operator **
    
    func ** (lhs: String, rhs: String) -> Bool {
        return lhs.contains(rhs)
    }
    
    let isContains: Bool = "abc"**"a" // true
    *lhsおよびrhs:lhsおよびrhs.演算子関数を作成するとき、関数のパラメータを記述するときに変数名としてよく使用されます.
    他のコードのようにグローバル関数で実装されていますが、タイプ内で実装すると読みやすく理解しやすくなります.
    class Car {
        var model: String
        var year: Int
        
        init(_ model: String, _ year: Int) {
            self.model = model
            self.year = year
        }
    }
    
    func == (lhs: Car, rhs: Car) -> Bool {
        return lhs.model == rhs.model
    }
    
    let carA = Car("A", 2010)
    let carB = Car("A", 2011)
    carA == carB /// true
    struct Phone {
        var company: String?
        var model: String?
    }
    
    func == (lhs: Phone, rhs: Phone) -> Bool {
        return lhs.model == rhs.model
    }
    
    let phoneA = Phone(company: "Apple", model: "A")
    let phoneB = Phone(company: "Apple", model: "B")
    phoneA == phoneB // false
    タイプ内でタイプメソッドに変更します.タイプ内に==関数を追加し,Carクラスのインスタンス間で演算してもよいし,Phone構造体間で演算してもよい.
    class Car {
        var model: String
        var year: Int
        
        init(_ model: String, _ year: Int) {
            self.model = model
            self.year = year
        }
        
        static func == (lhs: Car, rhs: Car) -> Bool {
            return lhs.model == rhs.model
        }
    }
    
    let carA = Car("A", 2010)
    let carB = Car("A", 2011)
    carA == carB /// true
    struct Phone {
        var company: String?
        var model: String?
        
        static func == (lhs: Phone, rhs: Phone) -> Bool {
            return lhs.model == rhs.model
        }
    }
    
    let phoneA = Phone(company: "Apple", model: "A")
    let phoneB = Phone(company: "Apple", model: "B")
    phoneA == phoneB // false