【问题标题】:Swift compiler can't check for protocol typeSwift 编译器无法检查协议类型
【发布时间】:2022-01-04 02:11:26
【问题描述】:

关于以下代码:

protocol BananaProtocol {
    var banana: Bool { get}
}

class MyBanana: BananaProtocol {
    var banana = true
}

protocol BananaProvider {
    var provider: BananaProtocol { get }
}

class BananaProviderImpl: BananaProvider {
    var provider = MyBanana()
}

编译器报错:Type 'BananaProviderImpl' does not conform to protocol 'BananaProvider'

如果我改为:

class BananaProviderImpl: BananaProvider {
    var provider = MyBanana() as BananaProtocol
}

有效。

为什么编译器不能推断 MyBanana 是 BananaProtocol 类型,因为它在类签名上? class MyBanana: BananaProtocol

对于理解此问题的帮助,我将不胜感激。 谢谢。

【问题讨论】:

  • var provider: BananaProtocol = MyBanana() 也可以。 Swift 可能(猜测)正在查看 var provider = MyBanana() 并决定将其设为 var provider: MyBanana = MyBanana(),这显然意味着您没有实现 BananaProvider 的要求 ????‍♂️
  • 在我看来,Swift 在打字方面非常挑剔。在定义这些类型时它有一些期望,在大多数情况下var provider: BananaProtocol = MyBanana() 是最优雅的,因为您可以在某些情况下使用as 来强制类型。在我自己的项目中,我几乎总是为每个变量定义类型,即使它不是非常复杂的情况。看起来漂亮整洁,实际上可以防止您在为这些变量分配新值或对象时出现编码错误。

标签: swift swift5 swift-protocols


【解决方案1】:

采用协议的类型与存在的协议不是一回事。 (例如,MyBanana 不是 BananaProtocol。)

建议:永远不要使用existentials。

protocol BananaProvider {
  associatedtype Banana: BananaProtocol
  var provider: Banana { get }
}

class BananaProviderImpl: BananaProvider {
  var provider = MyBanana()
}

【讨论】:

  • 这是一个有趣的解决方法,谢谢。但是你能详细说明“从不使用存在主义”吗?像上面建议的那样做var provider: BananaProtocol = MyBanana() 似乎是一个完美的好解决方案。谢谢!
  • 这不是很有趣——这就是 Swift 中的一般做法,因为您在评论中显示的代码实际上一点也不好!而且这个问题太大了,在这里不谈。 Existentials 通常比无用更糟糕——它们不能描述问题(例如,尝试在 BananaProviderImpl 中使用 BananaProtocol 而不是 MyBanana——这是可怕的 UX),并且存在性能问题。从这里开始? forums.swift.org/t/improving-the-ui-of-generics/22814 请参阅 SwiftUI.View 了解不使用存在的最佳示例。
猜你喜欢
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多