[75%]オプションと非オプションタイプの間で演算子を使用できる原理


SWIFTはOptionalタイプと非Optionalタイプの比較演算子(=,!=など)を使用できることを発見した.
今回のプレゼンテーションでは、SWIFTの演算子がどのように具体的に定義されているかを見てみましょう.これは可能です.

演算子の構文の定義

  • 参考:SWIFT公式ドキュメント-カスタマーオペレータ
  • 例題で確認するのが一番早いはずです
    prefix operator +++
    infix operator ===
    postfix opertaor ---
    
    struct Vector2D {
        var x = 0
        var y = 0
        // prefix ( +++A )
        static prefix func +++ (vector: inout Vector2D) -> Vector2D {
            vector.x += 1
            vector.y += 1
            return vector
        }
        
        // infix ( A === B )
        static func === (left: Vector2D), right: Vector2D) -> Vector2D {
            return Vector2D(x: left.x + right.x, y: left.y + right.y)
        }
        
        // postfix ( A--- )
        static postfix func --- (vector: Vector2D) -> Vector2D {
            vector.x -= 1
            vector.y -= 1
            return vector
        }
    }
    要するに、
    1.まずglobalでオペレータ登録を行うpostfixまたはprefixとして表すタイプの方法
    (infixなら省略可能)

    では、「non-optional==Optional」構文では、比較演算子はどのタイプの定義に従うのでしょうか。


    実際、infix演算子では、左手でも右手でも、メソッドではなく一般的な関数として定義できます.
    つまり、どこで定義してもグローバルです
    △書類に書いてあるのではなく、実験の結果はこうだった.
    また、特定のタイプの定義セクションでタイプメソッドを使用して実装する場合は、コンパイルエラーを回避するには、左でも右でも1つのタイプが必要です.
    証拠として、以下のコードが機能していることを確認します.
    struct ABC {
        let k = 3
        static func == (left: ABC, right: ABC?) -> String {
            return "left-hand is Optional"
        }
        static func == (left: ABC?, right: ABC) -> String {
            return "right-hand is Optional"
        }
    }
    
    func == (left: ABC?, right: ABC?) -> String {
        return "both-hands are Optional"
    }
    
    
    let temp: ABC = ABC()
    let optTemp: ABC? = ABC()
    
    print(temp == optTemp) // right-hand is Optional
    print(optTemp == temp) // left-hand is Optional
    print(optTemp == optTemp) // both-hands are Optional

    SWIFT標準ライブラリがどのように実現されているかを見てみましょう


    SWIFT標準ライブラリで「オプションタイプ比較」演算子を実装する方法を見てみましょう
    extension Optional : Equatable where Wrapped : Equatable {
        ...
        
        @inlinable public static func == (lhs: Wrapped?, rhs: Wrapped?) -> Bool
        
        ...
    }
    うん...?どちらも選択がある場合、どのように選択と無選択を比較することができますか?
    いくつかの実験結果は
    「オプション」と「非オプション」の間の演算子を使用する場合.
    左、右の組み合わせの演算子が個別に定義されていない場合でも.
    SWIFTで自動Wrapping non-Optionのように見えます
    そして、このような注釈を発見することができる.

    では、各タイプの組合せにすべての演算子を定義すると、何が実行されますか?


    ちなみに、ここのタイプの組み合わせは以下の場合です
  • left: Optional/right: Optional
  • left: Optional/right: non-Optional
  • left: non-Optional/right: Optional
  • left: non-Optional/right: non-Optional
  • 知りたいのは、
    「オプション」と「非オプション」の間のInfix演算子を使用する場合.
    1)Wrappingから開始するかどうか、左/右ともにオプションの演算子定義を実行します.
    2)組合せによって定義された演算子が存在するかどうかをチェックし、存在しない場合のみWrappingする.
    例として、どちらが正しいかチェックしてみました
    struct ABC {
        let k = 3
        static func == (left: ABC, right: ABC?) -> String {
            return "left-hand is Optional"
        }
        static func == (left: ABC?, right: ABC) -> String {
            return "right-hand is Optional"
        }
    }
    
    func == (left: ABC?, right: ABC?) -> String {
        return "both-hands are Optional"
    }
    
    let temp: ABC = ABC()
    let optTemp: ABC? = ABC()
    
    print(temp == optTemp) // right-hand is Optional
    print(optTemp == temp) // left-hand is Optional
    print(optTemp == optTemp) // both-hands are Optional
    要するに2番は正しい
    まず、この組合せで定義された演算子が存在するかどうかを決定します.
    ない場合は、Wrappingはオプションではありません.
    両方ともOptionで定義された演算子を実行します
    くさびを増やすために、結果を表示するには、Optional+Optionalタイプの組合せ演算子のみを定義します.
    struct ABC {
        let k = 3
    }
    
    func == (left: ABC?, right: ABC?) -> String {
        return "both-hands are Optional"
    }
    
    let temp: ABC = ABC()
    let optTemp: ABC? = ABC()
    
    print(temp == optTemp) // both-hands are Optional
    print(optTemp == temp) // both-hands are Optional
    print(optTemp == optTemp) // both-hands are Optional
    すべての出力は「two-hands are Optional」です.
    SWIFTは自動包装であることがわかります

    今日の結論


    Infix演算子は、「オプション」と「非オプション」の間で使用します。


    1)まず,同じ組合せの演算子定義があるかどうかを特定し,ある場合に実行する.
    2)そうでない場合、オプション/オプションの組み合わせのみが定義されている場合、SWIFTは自動的にWrapping非オプションタイプになります