除了冗余的介绍之外,我想要有这样的东西:
let collection : Any<Sequence where .Iterator.Element == String> = ...
或
let collection : Sequence<where .Iterator.Element == String> = ...
这被称为&#34;广义存在&#34;在Apple's Generics Manifesto。 (我认为)我真的需要这个用于许多用例和这个:
协议&#39; P&#39;只能用作通用约束因为 它有自我或相关的类型要求。
制作&#34;第一个面向协议的语言&#34;对我来说很难理解。缺乏这一点使我与Swift的类型系统作斗争并创造了不利的通用&#34;抽象&#34;应该有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)
}
}
虽然我可以描述GenericClassDelegate
协议,但我(目前在Swift 3中)不能拥有该类型的变量或常量(或任何符合限制的类型)。
不要将此问题与How to use generic protocol as a variable type或Swift delegate protocol for generic class混淆,因为我的问题是:
P.S。当你在封闭中捕获代表的功能时,不要建议使用类型擦除的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)
答案 0 :(得分:4)
目前是否有关于将广义存在引入Swift的任何提案或讨论,计划是什么?如果不是,我该如何参与并对此产生影响?
这是一个常见的功能,并且已经有快速进化的初步设计工作。但此时,核心团队和社区正在关注影响功能的ABI稳定性,或Lattner定义为&#34; Swift 4 Phase 1&#34;。
第2阶段开始时你肯定会听到更多关于它的信息。鉴于其受欢迎程度,预计它将成为Swift 4的一部分。
如果以这种方式设计Swift(使用Associated Types,但没有Generalized Existentials),也许它意味着一些架构转变。我期望用?
替换委托模式
您可以使用类型擦除的包装器作为传递解决方案。通常,它利用动态分派和类的继承来擦除类型。
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))
您可以查看how the Standard Library implements type-erased wrappers。
答案 1 :(得分:0)
该代码不正确。刚编译的正确代码是:
protocol Fancy {
associatedtype Value
var value: Value {get set}
}
struct FancyMatter<Value>: Fancy {
var value: Value
}
class AnyFancyBoxBase<P: Fancy>: 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(value: 1))
// prove it out
print (AnyFancyBoxBase(FancyMatter(value: 1)).value)
print (box.value)