自定义运算符错误 - 无法传递不可变值

时间:2017-11-22 15:04:15

标签: swift

我做错了什么?我试图了解自定义运算符如何在swift中运行。

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

我怎样才能让它发挥作用?

2 个答案:

答案 0 :(得分:0)

这与您的自定义运算符无关,这很好(尽管为什么不只是使用赋值?)

inout值必须是可变的。表达式myClass?.value的类型是不可变的Optional<String>。这是因为可选链接,不像myClass!.value强制解包myClass然后应用成员访问。

答案 1 :(得分:0)

问题是<<在语义上是一个非变异的运算符。因此,precedencegroup未定义assignment属性设置为true,这意味着运算符不遵循与可选链接相同的分组规则。

因此,<<的重载不能与可选链接一起使用(但即使它可以;您不应该使用变异实现重载非变异操作符,这只会令人困惑)。

如果您要将assignment设置为true的运算符重载,那么您的代码就可以正常工作了。例如,它可以与<<=一起使用 - 虽然实际上并没有这样做,因为<<=已经具有已确定的含义(就地左位移位),这是你不符合的。 / p>

如果真的需要运营商;我建议你定义自己的:

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。后者很多更清晰,只有几个额外的字符。