繁体   English   中英

Swift枚举涉及依赖协议的多种泛型类型

[英]Swift enum multiple generic types involving depending protocols

protocol ProtocolA {
    func someFunc() -> Any
}

protocol ProtocolB: ProtocolA {
    var someVar: Any { get }
}

enum MyEnum<T: ProtocolA, U: ProtocolB> {
    case A(T)
    case B(U)
}

protocol DataObject {
    ...
}

extension DataObject where Self: ProtocolB {
    func doSomething() {
        let x = MyEnum.B(self)
        /// Compiler error:
        /// Cannot invoke 'B' with an argument list of type '(Self)'
    }
}

我不明白为什么上面给我一个错误。 奇怪的是,删除两个枚举通用约束中的任何一个,使枚举只有一个约束,解决了问题......

请注意,ProtocolB扩展了ProtocolA。 与通用约束一起使用时,是否不支持此功能?


UPDATE

MyEnum更改MyEnum可以解决问题:

enum MyEnum {
    typealias T = ProtocolA
    typealias U = ProtocolB

    case A(T)
    case B(U)
}

但是,我仍然不明白为什么......

这个错误有点误导。 让我们简化问题来探索它。

protocol ProtocolA {}

protocol ProtocolB: ProtocolA {}

enum MyEnum<T: ProtocolA, U: ProtocolB> {
    case A(T)
    case B(U)
}

struct AThing: ProtocolA {}

struct BThing: ProtocolB {}

let bThing = BThing()
let thing = MyEnum.B(bThing) // error: cannot invoke 'B' with an argument list of type '(BThing)'

所以现在我们DataObject了同样的问题而不需要DataObject 为什么这会失败?

MyEnum是通用的。 这意味着为了创建具体类型,它必须知道TU的类型。 您提供了对这些类型的约束(一个符合ProtocolA ,另一个符合ProtocolB ),但您没有具体说明它们是什么类型。

当我们到达这一行时:

let thing = MyEnum.B(bThing)

什么类型的thing 通过类型推断,我们可以弄清楚U是什么,但是什么是T

let thing: MyEnum<?, BThing> = MyEnum.B(bThing)

这里没有足够的上下文来解决它,所以我们必须明确地告诉编译器:

let thing = MyEnum<AThing, BThing>.B(bThing)

所以完整类型的thingMyEnum<AThing, BThing> ,这是一种与MyEnum<OtherAThing, BThing>不同的类型。 (正如[Int][String]类型不同,这就是为什么let xs = []在没有显式类型定义的情况下不会编译。)

你的第二个例子不通用,所以没有问题。 它简化为:

enum MyEnum {
    case A(ProtocolA)
    case B(ProtocolB)
}

绑定类型只是重命名类型,它们不会创建新类型(如未绑定的类型,或者Swift 2.2调用它, associatedtype )。 所以我们知道A接受任何ProtocolAB接受任何ProtocolB ,并且所有MyEnum实例具有相同的类型。

错误是不幸的,因为编译器很困惑。 如果将此简化为最基本的情况,则会得到更明确的错误。 这失败的原因与您的示例完全相同。

enum MyEnum<T> {
    case A
}

let x = MyEnum.A // error: generic parameter 'T' could not be inferred

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM