【问题标题】:Type cannot conform to a protocol with a member that has the same name but is optional类型不能符合具有相同名称但可选的成员的协议
【发布时间】:2019-07-23 21:17:57
【问题描述】:

我有一个结构,其成员名为 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 {} 

错误具体说:

候选人具有不匹配的类型“字符串”

它还提供了一个修复:

您要添加协议存根吗?

但不出所料,这会导致重新声明错误。

extension SimpleStruct: SimpleProtocol {
    var email: String? {
        // Invalid redeclaration of 'email'
    }
}

我知道StringOptional<String> 是不同的类型,但我希望简单地说SimpleStruct 符合SimpleProtocol 而无需额外代码应该编译,原因与我可以将字符串传递给一个需要可选字符串的函数。有人可以解释我为什么错了吗?

注意:我意识到我可以通过多种方式解决这个问题,最明显的是重命名 SimpleProtocol 中的 email 字段。但我想了解为什么这是必要的,并想知道是否有更优雅的解决方案。

【问题讨论】:

  • 这基本上与Why can't a get-only property requirement in a protocol be satisfied by a property which conforms? 中的限制相同,除了协议类型的 get-only 属性要求由符合类型的属性满足,您正在寻找更通用的子类型关系。没有技术上的原因不可能,只是还没有实现(尽管不幸的是,现在的实现会带来源兼容性问题)。
  • @Hamish 感谢您链接到该问题,感谢您在此处回答的详细信息!
  • 我会说惊喜是另一种方式。给定一个包装了 String 的 Optional,将 String 直接分配给它是合法的,这很奇怪。你已经习惯了,但它是基于语言中一些奇怪的机制。毕竟你不能在期望Wrapper<String>的地方分配一个字符串。

标签: swift


【解决方案1】:

就像你说的,StringString? 不是同一个类型,如果你的类型不匹配,你根本就不能遵守协议。

想象一下如果协议声明像这样的变量{ get set } 并且另一个对象试图分配一个nil 值会发生什么。它会崩溃,因为您的类型实际上没有遵守协议。

你可以做的是创建另一个不是可选的变量并将值存储在那里,然后像这样实现email

var email: String? { return emailValue }

这样你就有了你想要的非可选但仍然符合协议。但完全按照自己的意愿去做是不可能的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多