swift - 协议(protocol)不符合自身?

标签 swift generics swift-protocols

为什么此Swift代码无法编译?

protocol P { }
struct S: P { }

let arr:[P] = [ S() ]

extension Array where Element : P {
    func test<T>() -> [T] {
        return []
    }
}

let result : [S] = arr.test()


编译器说:“类型P不符合协议P”(或在Swift的更高版本中,“不支持将'P'作为符合协议'P'的具体类型使用。”)。

为什么不?某种程度上,这感觉就像是语言上的一个漏洞。我意识到问题源于将数组arr声明为协议类型的数组,但这是不合理的事情吗?我认为协议确实可以帮助提供类型分层结构之类的结构吗?

最佳答案

编辑:使用Swift还要工作18个月,Swift是另一个主要版本(提供新的诊断),并且@AyBayBay的评论使我希望重写此答案。新的诊断是:


  “不支持将“ P”用作符合协议“ P”的具体类型。”


这实际上使整个事情变得更加清晰。此扩展名:

extension Array where Element : P {


Element == P时不适用,因为P不被视为P的具体符合。 (下面的“放在盒子里”解决方案仍然是最通用的解决方案。)



旧答案:

这是元类型的另一种情况。斯威夫特(Swift)确实希望您对大多数不重要的事情都采取具体的态度。 [P]不是具体类型(您不能为P分配大小已知的内存块)。 (我不认为这是真的,您绝对可以创建大小为P的东西,因为it's done via indirection。)我不认为有任何证据表明这是“不应该”工作的情况。这看起来非常像他们的“不起作用”案例之一。 (不幸的是,要让Apple确认这两种情况之间的区别几乎是不可能的。)Array<P>可以是变量类型(Array不能)的事实表明他们已经朝这个方向做了一些工作,但是Swift元类型具有很多锋利的边缘和未实现的案例。我认为您不会比这得到更好的“为什么”答案。 “因为编译器不允许。” (不满意,我知道。我整个Swift生活...)

解决方案几乎总是将东西放在盒子里。我们建立一个类型擦除器。

protocol P { }
struct S: P { }

struct AnyPArray {
    var array: [P]
    init(_ array:[P]) { self.array = array }
}

extension AnyPArray {
    func test<T>() -> [T] {
        return []
    }
}

let arr = AnyPArray([S()])
let result: [S] = arr.test()


当Swift允许您直接执行此操作(我最终希望这样做)时,很可能只是通过自动为您创建此框即可。递归枚举正是有这个历史的。您必须将它们装箱,这令人难以置信的烦人和限制,然后最终编译器添加了indirect来更自动地执行相同的操作。

关于swift - 协议(protocol)不符合自身?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46213254/

相关文章:

java - 返回类型 Class<> 之前的 Generic <> 是什么意思

java - 当类具有多个不同的字段时,如何对其进行泛化?

objective-c - 在 Swift 中实现 Objective C 委托(delegate)

swift - 自身,协议(protocol)扩展和非最终类

javascript - 如何通过节点js获取交易结果Firebase中的值(value)

ios - ScrollView 中的 Refreshcontrol 无法快速工作

ios - 使用扩展创建自定义 UIButton

ios - SpriteKit 中的 "nonuniformly scaled texture"是什么意思?

Java 泛型 - 从 T 到 T 的类型不匹配

swift - 有没有办法允许 Swift 协议(protocol)扩展访问实现所述协议(protocol)的类中的某些内容,但其他任何东西都无法访问?