我做错了什么?我试图了解自定义运算符如何在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
我怎样才能让它发挥作用?
答案 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
。后者很多更清晰,只有几个额外的字符。