【问题标题】:Swift: Determine whether a type conforms to protocol results an errorSwift:确定类型是否符合协议导致错误
【发布时间】:2021-11-10 17:09:41
【问题描述】:

当我试图确定一个类型是否符合协议时,我得到一个错误:

Protocol 只能用作泛型约束,因为它具有 Self 或关联的类型要求

这是我的代码的简化版本:

protocol FooProtocol {
    static func combine(foo: Self, with element: Any) -> Self
}

func combine<T>(foo: T, with element: Any) -> T? {
    if let F = T.self as? FooProtocol.Type { // Error in here
        return F.combine(foo: foo, with: element)
    } else {
        return nil
    }
}

我知道我可以这样做:

func combine<T: FooProtocol>(foo: T, with element: Any) -> T {
    return T.combine(foo: foo, with: element)
}

但这不是我需要的,我需要的是你可以调用任何类型的combine(foo:with:)函数,如果这个类型不符合FooProtocol那么nil会被返回。

谢谢!

【问题讨论】:

  • 您不需要运行时检查。只需做两个重载。
  • 什么意思?

标签: ios swift protocols


【解决方案1】:

您可以对此combine 函数的多个重载进行编译时检查,如下所示:

func combine<T: FooProtocol>(foo: T, with element: Any) -> T {
    T.combine(foo: foo, with: element)
}

func combine<T>(foo: T, with element: Any) -> T? {
    nil
}

用法:

struct StructA: FooProtocol {
    /* conformance, etc... */
}

struct StructB {}

combine(foo: StructA(), with: 1) // Type of StructA
combine(foo: StructB(), with: "1") // Type of StructB?, return nil

这和我的回答here是同一个概念。

【讨论】:

  • 只有在编译时可以证明 foo 的最终类型符合 FooProtocol 时才有效。如果对combine 的调用发生在另一个泛型方法中,或者在采用另一个协议的方法中,则此信息将丢失,并且将调用错误的方法。模棱两可的泛型专业化非常脆弱,是非常令人沮丧的错误的根源。
  • 有关失败的一些示例,请参阅gist.github.com/rnapier/6765a48a55d628433add84d0adadbf08
  • @RobNapier 谢谢你的补充,这对了解很有用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多