gpt4 book ai didi

swift - 以协议(protocol)和符合类(!)实例作为参数的函数

转载 作者:搜寻专家 更新时间:2023-10-30 22:18:46 25 4
gpt4 key购买 nike

我正在尝试弄清楚如何定义一个采用以下内容的函数两个参数:

  1. 协议(protocol)。
  2. 符合该协议(protocol)的(引用类型)的实例。

例如给定

protocol P { }
class C : P { } // Class, conforming to P
class D { } // Class, not conforming to P
struct E: P { } // Struct, conforming to P

这应该编译:

register(proto: P.self, obj: C()) // (1)

但这些不应该编译:

register(proto: P.self, obj: D()) // (2)  D does not conform to P
register(proto: P.self, obj: E()) // (3) E is not a class

如果我们去掉第二个参数是类实例的条件就很容易了:

func register<T>(proto: T.Type, obj: T) {
// ...
}

但这也会接受 (3) 中的结构(值类型)。这看起来很有希望并且可以编译

func register<T: AnyObject>(proto: T.Type, obj: T) {
// ...
}

但是 (1)(2)(3) 都不再编译,例如

register(proto: P.self, obj: C()) // (1)
// error: cannot invoke 'register' with an argument list of type '(P.Protocol, obj: C)'

假设编译器错误的原因与 Protocol doesn't conform to itself? .

另一个失败的尝试是

func register<T>(proto: T.Type, obj: protocol<T, AnyObject>) { }
// error: non-protocol type 'T' cannot be used within 'protocol<...>'

一个可行的替代方案是一个接受参数的函数

  1. 协议(protocol)。
  2. 符合该协议(protocol)的类型实例。

这里的问题是如何限制第一个参数使得只有类协议(protocol)被接受。

背景:我最近偶然发现了 SwiftNotificationCenter实现面向协议(protocol)的类型安全通知机制的项目。它有一个 register看起来像这样的方法:

public class NotificationCenter {

public static func register<T>(protocolType: T.Type, observer: T) {
guard let object = observer as? AnyObject else {
fatalError("expecting reference type but found value type: \(observer)")
}

// ...
}

// ...
}

然后观察者被存储为弱引用,这就是为什么他们必须是引用类型,即类的实例。但是,这仅在运行时检查,我想知道如何使其成为编译时检查。

我是否遗漏了一些简单/明显的东西?

最佳答案

你不能直接做你想做的事。它与引用类型无关,这是因为任何约束都会使 T存在性,因此当您引用协议(protocol)的元类型 P.self: P.Protocol 时,不可能在调用站点满足它们和收养者 C . T 时有一种特殊情况是不受约束的,允许它首先工作。

到目前为止,更常见的情况是约束 T: P并要求 P: class因为对于任意协议(protocol)的元类型,您唯一可以做的事情就是将名称转换为字符串。它恰好在这种狭窄的情况下很有用,仅此而已;签名也可以是 register<T>(proto: Any.Type, obj: T)对于它会带来的所有好处。

理论上 Swift 可以支持对元类型的约束,ala register<T: AnyObject, U: AnyProtocol where T.Type: U>(proto: U, obj: T)但我怀疑它在许多情况下是否有用。

关于swift - 以协议(protocol)和符合类(!)实例作为参数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37707450/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com