我有一个结构,其成员名为email
,类型为String
,并且有一个协议,其成员名为email
,类型为String?
。我认为使结构符合该协议应该是微不足道的,因为它具有必要的信息,但是我被编译器所阻止。这是我在操场上放在一起的精简示例:
struct SimpleStruct {
let email: String
}
protocol SimpleProtocol {
var email: String? { get }
}
// Type 'SimpleStruct' does not conform to protocol 'SimpleProtocol'
extension SimpleStruct: SimpleProtocol {}
该错误专门说明:
候选人的类型不匹配'String'
它还提供了一个解决方法:
您要添加协议存根吗?
但毫不奇怪,这会导致重新声明错误。
extension SimpleStruct: SimpleProtocol {
var email: String? {
// Invalid redeclaration of 'email'
}
}
我知道String
和Optional<String>
是不同的类型,但是我希望简单地说SimpleStruct
符合SimpleProtocol
且无需编译其他代码即可我可以将字符串传递给需要可选字符串的函数的原因。有人可以解释为什么我弄错了吗?
注意:我意识到我可以通过多种方式解决此问题,最著名的是重命名email
中的SimpleProtocol
字段。但是我想了解为什么这样做是必要的,并且想知道是否有更优雅的解决方案。
答案 0 :(得分:0)
就像您说的那样,String
和String?
不是同一类型,如果您的类型不匹配,您就根本无法遵循协议。
想象一下,如果协议声明了这样的变量{ get set }
,而另一个对象试图分配一个nil
值,将会发生什么。由于您的类型实际上不遵守该协议,因此会崩溃。
您可以做的是创建另一个非可选变量,并在其中存储值,然后像这样实现email
:
var email: String? { return emailValue }
这样,您便拥有了所需的非可选内容,但仍符合协议。但是不可能完全按照自己的意愿做。