Swift类型推断不起作用(Xcode 7.1.1)

时间:2015-12-03 01:57:20

标签: xcode swift generics protocols

这是我关于StackOverflow的第一个问题,所以请放轻松我。

我一直在努力让Swift调用适当的泛型重载。

假设我有以下协议 -

=IF(B1="", "", IF(ISNUMBER(SEARCH("*FIG*", B1)), "FIG", IF(ISNUMBER(SEARCH("*SF*", B1)), "SF", IF(ISNUMBER(SEARCH("*AF*", B1)), "AF&L",  IF((ISNUMBER(SEARCH("*IB*", B1))),  IF(ISNUMBER(SEARCH("*ASIA*", B1)), "IBAsia", "IBexA"))))))

我有以下通用方法 -

protocol MyProtocol { }

可以预期,使用符合func foo<T>() -> T func foo<T: MyProtocol>() -> T 的返回类型foo()调用T会调用适当的重载。

MyProtocol

上面的代码实际上在运行时调用了以下函数,IDE中的Cmd + Click也导航到了错误的重载。

let bar: MyProtocol = foo()

出于某种原因,我无法在Xcode 7.1.1中正常使用它。

我是否遗漏了一些完全基本的东西,或者这是另一个斯威夫特的怪癖?

修改

根据matt的请求添加此行为的示例。

func foo<T>() -> T

将上述代码复制并粘贴到Swift命令行应用程序中并执行产生以下输出。

protocol MyProtocol { }

class MyProtoClass : MyProtocol { }

class Bar {

    func foo<T>(value: T) {
        print("T is Generic")
    }

    func foo(value: MyProtocol) {
        print("T conforms to MyProtocol")
    }
}

class MyClass<T> {

    var value: T
    init(value: T) { self.value = value }
    var b = Bar()

    func print() {
        b.foo(value)
    }
}

MyClass<MyProtocol>(value: MyProtoClass()).print()
MyClass<String>(value: "").print()

2 个答案:

答案 0 :(得分:1)

我认为这里的问题是泛型中的协议(通常在Swift中)不能按照您希望的方式工作。他们不是一流的类型。我知道这很模糊......但是这样看待它;如果你删除了func foo<T>(value: T) foo版本,你的代码甚至都不会编译。换句话说,Swift没有选择foo并选择错误;它说b.foo(a1.value)不会调用func foo<T: MyProtocol>(value: T)

我有一种模糊的感觉,这与我的问题有关:

Protocol doesn't conform to itself?

答案 1 :(得分:0)

好的,我将在这里回答我自己的问题。

经过一些调查后,似乎Swift希望您在泛型参数上实现一个带有类型约束的扩展。

extension MyClass where T : MyProtocol {
    func print() {
        b.foo(value)
    }
}

我知道这并没有真正解决问题,但这足以让我在现实世界的用例中解决问题。

上面的示例最终会显示如下内容。

protocol MyProtocol { }

class MyProtoClass : MyProtocol { }

class Bar {

    func foo<T>(value: T) {
        print("T is Generic")
    }

    func foo(value: MyProtocol) {
        print("T conforms to MyProtocol")
    }
}

class MyClass<T> {

    var value: T
    init(value: T) { self.value = value }
    var b = Bar()

    func print() {
        b.foo(value)
    }
}

extension MyClass where T : MyProtocol {

    func print() {
        b.foo(value)
    }
}

MyClass<MyProtoClass>(value: MyProtoClass()).print()
MyClass<String>(value: "").print()