Swift 协议可选一致性通过非可选
Swift Protocol Optional conformance via Non-Optional
我有一个带有可选 属性 的协议。
大多数符合此协议的类型都会有一个匹配的可选 属性。但是,有一个具有相同类型和名称的非可选 属性。
protocol SomeProtocol {
var foo: Int? { get }
}
struct StructA: SomeProtocol {
let foo: Int?
}
struct StructB: SomeProtocol {
let foo: Int // Type 'StructB' does not conform to protocol 'SomeProtocol'
}
按 Xcode 的“修复 - 您要添加协议存根吗?”按钮添加了 属性 的可选版本,但结构现在具有无效的重复变量名称:
struct StructB: SomeProtocol {
let foo: Int
var foo: Int? { return foo } // Invalid redeclaration of 'foo'
}
在 { get }
-only 的情况下,我曾假设这会“正常工作”,因为非可选总是满足可选的约束,类似于你可以如何 return具有可选 return 类型的函数中的非可选。但显然不是这样。
这对函数也是一样的;声明 func bar() -> Int
.
的一致类型不满足协议的 func bar() -> Int?
有什么办法可以解决这个问题吗?我不想重命名变量或添加中间吸气剂。
Swift有考虑过这种情况吗?不允许非可选协议变量满足可选协议变量的合理性是什么?
如果协议提供了一个默认实现,returns一个可选的:
protocol SomeProtocol {
var foo: Int? { get }
}
extension SomeProtocol {
var foo: Int? { return nil }
}
protocol-conforming 类型然后可以提供 variable/function:
的覆盖 non-optional 版本
struct StructB: SomeProtocol {
let foo: Int
}
我在 Swift Evolution 论坛上发现了这个讨论:
At the first glance I thought there is a rule that allows us to satisfy protocol requirements with non-optional types, but this resulted in an error. Only after further investigation I noticed that a default implementation must exist in order to 'kind of override' the requirement with a non-optional version.
https://forums.swift.org/t/how-does-this-rule-work-in-regard-of-ambiguity/19448
这个 Swift 团队还讨论了允许 non-optional 类型满足 optional-value 协议:
Would it make any sense to allow protocol requirement satisfaction with non-optional types, like with failable init's? (Probably with some implicit optional promotion.)
是的,完全正确!除了这改变现有代码行为的部分,所以我们必须非常小心。这被认为是 [SR-522] Protocol funcs cannot have covariant returns
的一部分
在此处的 Stack Overflow 上进行了跟踪:
有助于让编译器识别一致性,但您需要了解这可能产生的奇怪行为。
新符合类型的对象将 return 一个不同的值,具体取决于您将其转换为哪种类型(这也包括传递类型为协议的参数):
let bar = StructB(foo: 7)
let baz: SomeProtocol = bar
bar.foo // evaluates to 7
baz.foo // evaluates to nil (surprise!)
最近有人评论了相关的 Swift 错误票:"This can be quite surprising and perhaps could be considered a bug of its own?"
这绝对把我绊倒了。
我有一个带有可选 属性 的协议。
大多数符合此协议的类型都会有一个匹配的可选 属性。但是,有一个具有相同类型和名称的非可选 属性。
protocol SomeProtocol {
var foo: Int? { get }
}
struct StructA: SomeProtocol {
let foo: Int?
}
struct StructB: SomeProtocol {
let foo: Int // Type 'StructB' does not conform to protocol 'SomeProtocol'
}
按 Xcode 的“修复 - 您要添加协议存根吗?”按钮添加了 属性 的可选版本,但结构现在具有无效的重复变量名称:
struct StructB: SomeProtocol {
let foo: Int
var foo: Int? { return foo } // Invalid redeclaration of 'foo'
}
在 { get }
-only 的情况下,我曾假设这会“正常工作”,因为非可选总是满足可选的约束,类似于你可以如何 return具有可选 return 类型的函数中的非可选。但显然不是这样。
这对函数也是一样的;声明 func bar() -> Int
.
func bar() -> Int?
有什么办法可以解决这个问题吗?我不想重命名变量或添加中间吸气剂。
Swift有考虑过这种情况吗?不允许非可选协议变量满足可选协议变量的合理性是什么?
如果协议提供了一个默认实现,returns一个可选的:
protocol SomeProtocol {
var foo: Int? { get }
}
extension SomeProtocol {
var foo: Int? { return nil }
}
protocol-conforming 类型然后可以提供 variable/function:
的覆盖 non-optional 版本struct StructB: SomeProtocol {
let foo: Int
}
我在 Swift Evolution 论坛上发现了这个讨论:
At the first glance I thought there is a rule that allows us to satisfy protocol requirements with non-optional types, but this resulted in an error. Only after further investigation I noticed that a default implementation must exist in order to 'kind of override' the requirement with a non-optional version.
https://forums.swift.org/t/how-does-this-rule-work-in-regard-of-ambiguity/19448
这个 Swift 团队还讨论了允许 non-optional 类型满足 optional-value 协议:
Would it make any sense to allow protocol requirement satisfaction with non-optional types, like with failable init's? (Probably with some implicit optional promotion.)
是的,完全正确!除了这改变现有代码行为的部分,所以我们必须非常小心。这被认为是 [SR-522] Protocol funcs cannot have covariant returns
的一部分
在此处的 Stack Overflow 上进行了跟踪:
新符合类型的对象将 return 一个不同的值,具体取决于您将其转换为哪种类型(这也包括传递类型为协议的参数):
let bar = StructB(foo: 7)
let baz: SomeProtocol = bar
bar.foo // evaluates to 7
baz.foo // evaluates to nil (surprise!)
最近有人评论了相关的 Swift 错误票:"This can be quite surprising and perhaps could be considered a bug of its own?"
这绝对把我绊倒了。