Swift 广义存在 [英] Swift Generalized Existentials

查看:22
本文介绍了Swift 广义存在的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

抛开冗长的介绍,我想要这样的东西:

Redundant introduction aside, I want to have something like this:

let collection : Any<Sequence where .Iterator.Element == String> = ...

let collection : Sequence<where .Iterator.Element == String> = ...

这在 中称为广义存在"Apple 的泛型宣言.(我认为)我真的需要这个用于许多用例和这个:

This is referred to as "Generalized existentials" in Apple's Generics Manifesto. (I think) I really need this for a number of use cases and this:

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

protocol 'P' can only be used as a generic constraint because it has Self or associated type requirements.

使第一个面向协议的语言"对我来说理解起来很麻烦.缺乏这一点让我与 Swift 的类型系统作斗争,并创建了不利的通用抽象"类,其中应该有一个带有 associatedtype 的协议.

makes "the first Protocol Oriented Language" be cumbersome for me to understand. Lack of this makes me fight Swift's type system and create adverse generic "abstract" classes where there should be a protocol with associatedtype.

这是一个让我印象最深刻的例子,一个泛型类的委托:

Here's one example, that hit me the most, delegate for a generic class:

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)
    }
}

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

While I can describe GenericClassDelegate protocol, I (currently in Swift 3) can't have a variable or constant of that type (or any type conforming to restrictions).

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

Don't confuse this question with How to use generic protocol as a variable type or Swift delegate protocol for generic class, as my questions are:

  1. 目前是否有关于将 Generalized Existentials 引入 Swift 的任何提议或讨论,有哪些计划?如果不是,我如何参与并影响它?
  2. 如果 Swift 是这样设计的(有关联类型,但没有通用存在),也许这意味着一些架构上的转变.我应该用什么来替换委托模式?

附言当您在闭包中捕获委托的函数时,不要建议使用类型擦除的 thunk,这是非常错误和误导性的,我什至称其为拐杖.

P.S. Don't suggest thunks with type erasure when you capture delegate's function in a closure, that is so much wrong and misleading, I'd even call it a crutch.

无意中找到了另一个解决方案,但我对它并不完全满意:

Accidentally found another solution, but I'm not satisfied with it completely:

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)

推荐答案

目前是否有任何关于将广义存在引入 Swift 的提议或讨论,有什么计划?如果不是,我如何参与并影响它?

Are there any proposals or discussions currently present on introducing Generalized Existentials into Swift, what are the plans? If no, how can I participate and affect this?

这是一个普遍要求的功能,并且已经有关于 swift-evolution 的初步设计工作.但此时,核心团队和社区正在关注影响特性的 ABI 稳定性,或者 Lattner 定义的Swift 4 Phase 1".

It is a commonly requested feature, and there was already preliminary design effort on swift-evolution. But at this moment, the core team and the community are focusing on ABI stability affecting features, or what Lattner defines as "Swift 4 Phase 1".

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

You would definitely hear more about it when Phase 2 commences. Given its popularity, it is expected to be part of Swift 4.

如果 Swift 是这样设计的(有关联类型,但没有通用存在),也许这意味着一些架构上的转变.我应该用什么代替委托模式?

If Swift was designed that way (with Associated Types, but without Generalized Existentials), maybe it implies some architectural shift. What am I expected to replace delegation pattern with?

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

You can use type-erased wrappers as a transitive solution. In general, it exploits the dynamic dispatch and the inheritance of classes to erase the type.

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))

你可以看看如何标准库实现类型擦除包装.

这篇关于Swift 广义存在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆