Swift广义存在

MAN*_*rii 6 generics delegates swift3

除了冗余的介绍,我希望有这样的东西:

let collection : Any<Sequence where .Iterator.Element == String> = ...
Run Code Online (Sandbox Code Playgroud)

要么

let collection : Sequence<where .Iterator.Element == String> = ...
Run Code Online (Sandbox Code Playgroud)

这被称为Apple的Generics Manifesto中的 "Generalized Existentials" .(我认为)我真的需要这个用于许多用例和这个:

协议'P'只能用作通用约束,因为它具有Self或相关类型要求.

使"第一个面向协议的语言"对我来说很难理解.缺乏这一点使我打击Swift的类型系统并创建不利的通用"抽象"类,其中应该有一个协议associatedtype.

这是一个让我受命最多的例子,代表一个泛型类:

protocol GenericClassDelegate : class {
    associatedtype ItemType
    func didDoThat(who : GenericClass<ItemType>) 
}

class GenericClass<T> {
    weak var delegate : GenericClassDelegate<where .ItemType == T>? // can't do that

    func notify() {
        delegate?.didDoThat(who: self)
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然我可以描述GenericClassDelegate协议,但我(目前在Swift 3中)不能具有该类型的变量或常量(或任何符合限制的类型).

不要混淆这个问题与如何将泛型协议用作泛型类的变量类型Swift委托协议,因为我的问题是:

  1. 目前是否有关于将广义存在引入Swift的任何建议或讨论,计划是什么?如果不是,我该如何参与并影响到这一点?
  2. 如果以这种方式设计Swift(使用Associated Types,但没有Generalized Existentials),也许它意味着一些架构转变.我期望用什么代替委托模式?

PS当你在一个闭包中捕获委托函数时,不建议使用类型擦除的thunk,这是多么错误和误导,我甚至称之为拐杖.

无意中发现了另一种解决方案,但我对此并不满意:

protocol GenericClassDelegate : class {
    associatedtype ItemType
    func didDoThat(who : GenericClass<ItemType, Self>)
}

class GenericClass<T, Delegate : GenericClassDelegate> where Delegate.ItemType == T {
    weak var delegate : Delegate?

    func notify() {
        delegate?.didDoThat(who: self)
    }

    init(_ delegate : Delegate?) {
        self.delegate = delegate
    }
}

// Delegates must be final classes, otherwise it does not compile
// because I used Self in GenericClassDelegate
final class GenericClassDelegateImp<T> : GenericClassDelegate {
    typealias ItemType = T
    func didDoThat(who: GenericClass<T, GenericClassDelegateImp>) {
        print(who)
    }
}

// Usage:
var delegate = GenericClassDelegateImp<Int>()
var genericClass = GenericClass<Int, GenericClassDelegateImp<Int>>(delegate)
Run Code Online (Sandbox Code Playgroud)

And*_*ers 5

目前在将通用存在性引入Swift中是否有任何建议或讨论,计划是什么?如果没有,我该如何参与并影响这一点?

这是一个普遍要求的功能,并且已经在快速进化方面进行了初步设计。但是目前,核心团队和社区正在关注影响功能的ABI稳定性,也就是Lattner定义的“ Swift 4 Phase 1”。

当第二阶段开始时,您肯定会听到更多有关它的信息。鉴于其受欢迎程度,它有望成为Swift 4的一部分。

如果Swift是按这种方式设计的(具有关联类型,但没有通用存在),则可能意味着某些架构上的转变。我期望用什么来代替委派模式?

您可以使用类型擦除的包装器作为传递解决方案。通常,它利用动态调度和类的继承来擦除类型。

protocol Fancy {
    associatedtype Value
    var value: Value
}

struct FancyMatter<Value> {
    let value: Value
}

class AnyFancyBoxBase<P: FancyProtocol>: AnyFancyBox<P.Value> {
    let base: P
    override var value: P.Value { return base.value }
    init(_ base: P) { self.base = base }
}

class AnyFancyBox<Value> {
    var value: Value { fatalError() }
}

var box: AnyFancyBox<Int> = AnyFancyBoxBase(FancyMatter(1))
Run Code Online (Sandbox Code Playgroud)

您可以看看标准库如何实现类型擦除的包装器