2017-11-22 9 views
0

私は間違っていますか?私はカスタムオペレータが迅速にどのように働くかを理解しようとしています。カスタム演算子エラー - 不変の値を渡すことができません

enum MyEnum: String { 
    case String = "String" 

    static func << (lhs: inout String?, rhs: MyEnum) { 
     lhs = rhs.rawValue 
    } 
} 

class MyClass { 

    var value: String? 

} 

let myClass: MyClass? = MyClass() 

myClass!.value << MyEnum.String 

myClass!.value // "String" 

myClass?.value << MyEnum.String // error: cannot pass immutable value of type 'String?' as inout argument 

どうすればいいですか?

+0

はい、動作します。すばらしいです!どうもありがとう! – user1841146

+0

ああ、これは演算子の 'precedencegroup'の' assignment'プロパティーのためです - このようなオプションの連鎖では 'true'を使う必要があります。 – Hamish

+0

これはカスタムタイプに対して '='を宣言できますか? – user1841146

答えて

0

(、なぜ単に割り当てを使用しない?が)

inout値は変更可能でなければなりません。これは、だけで結構ですカスタム演算子、とは何の関係もありません。式myClass?.valueの型は不変のOptional<String>です。これは、myClass!.valueとは違って、オプションの連鎖のために、myClassのアンラップを強制してから、メンバーアクセスを適用します。

+0

どうすれば 'myClass? 'のように動作させることができますか?.value =" some string " – user1841146

+0

@ user1841146いいえ、同じ問題があるからです。最初に 'myClass'をアンラップする必要があります。 – JeremyP

+0

私は割り当てをすると動作します。確認できます。 – user1841146

0

問題は、<<が意味的に非突然変異演算子であることです。そのようなものとして、assignmentプロパティがtrueに設定された状態で、そのprecedencegroupは定義されていません。これは、演算子がオプションの連鎖と同じグループ化規則に従わないことを意味します。

したがって、<<のオーバーロードは、オプションの連鎖と組み合わせて使用​​することはできません(ただし、可能であれば、変異していない演算子に過度の負荷をかけるべきではありません。

assignmenttrueに設定されているオペレータを過負荷にした場合、コードは正常に動作します。たとえば、<<=で動作しますが、これは実際には行っていません。<<=には、既に準拠していない確立された意味(インプレース左ビットシフト)が既に存在しています。

の場合、実際にはにはオペレータが必要です。私は、あなた自身を定義助言:

precedencegroup CustomAssignment { 
    assignment: true // Allow the operator to be used with optional chaining. 
} 

infix operator <~ : CustomAssignment 

enum MyEnum : String { 
    case string = "String" 

    static func <~ (lhs: inout String?, rhs: MyEnum) { 
    lhs = rhs.rawValue 
    } 
} 

class MyClass { 
    var value: String? 
} 

let myClass: MyClass? = MyClass() 

myClass?.value <~ MyEnum.string 
print(myClass?.value as Any) // Optional("String") 

は個人的に、しかし、私はちょうど
myClass?.value = MyEnum.string.rawValue上で、このようなオペレータの値が表示されません。後者はです.はほんの少し余分な文字で明瞭です。

+0

ありがとうございます!私はそれを私の心の中にとどめます。 – user1841146

+0

ありがとうございました。私は、演算子のオーバーロードの能力、できること、できないことを理解しようとしています。 C++では、覚えているように、演算子のオーバーロード、つまり任意のタイプの演算子のオーバーロードなど、何らかの操作を行うことができます。 – user1841146

+0

@ user1841146心配する必要はありません - Swiftはオペレータのオーバーロードにはまだまだ柔軟性がありますが、意味を確立している演算子にそれらを満たさない実装をオーバーロードさせないようにします(一番の例は '='のオーバーロードを許さない)。さらに、簡潔さのために明快さを犠牲にするべきではありません。型変換やプロパティへのアクセスが必要な場合は、それをカスタム演算子の下に埋め込むよりも明示的にする方が一般的です。 – Hamish

関連する問題