swift – 将协议和符合类(!)实例作为参数的函数

前端之家收集整理的这篇文章主要介绍了swift – 将协议和符合类(!)实例作为参数的函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图找出如何定义一个具有以下功能函数
两个参数:

>协议.
>符合该协议的类(引用类型)的实例.

例如,给定

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

这应该编译:

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

但这些不应该编译:

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

如果我们放弃第二个参数是类实例的条件,这很容易:

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

但这也会接受(3)中的struct(值类型).
这看起来很有希望和编译

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

但是,(1),(2),(3)中的任何一个都不再编译,例如

register(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<...>'

可行的替代方案是作为参数的函数

>类协议.
>符合该协议的类型的实例.

这里的问题是如何限制第一个参数
类协议被接受.

背景:我最近偶然发现了
SwiftNotificationCenter
实现面向协议的类型安全通知机制的项目.
它有一个
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存在,因此当您引用协议的元类型P.self:P.Protocol和采用者C时,不可能在调用站点满足它们.特殊情况,当T不受约束,允许它首先工作.

到目前为止,更常见的情况是约束T:P并且需要P:class,因为对于任意协议的元类型,你唯一可以做的就是将名称转换为字符串.它恰好在这种狭隘的情况下很有用,但就是这样;签名也可以注册< T>(proto:Any.Type,obj:T),它将做的所有好处.

从理论上讲,Swift可以支持约束元类型,ala寄存器< T:AnyObject,U:AnyProtocol其中T.Type:U>(proto:U,obj:T)但我怀疑它在许多情况下会有用.

猜你在找的Swift相关文章