如何调用更具体的重载方法

时间:2017-01-08 10:13:41

标签: swift generics overloading

这是一个示例游乐场:

protocol P {
    associatedtype T
    func getValue() -> T
}

class Foo: P {
    func getValue() -> String {
        return "hello"
    }
}

class Bar {
    func test<T: P>(_ o: T) {
        print("Generic", o.getValue())
    }

    func test(_ o: Any) {
        print("Any")
    }
}

let foo = Foo()
let bar = Bar()
bar.test(foo)

输出:Any

如果删除任何版本的test,则调用泛型方法。 类Foo符合协议P,为什么Swift不选择泛型方法,因为它更具体?有没有办法调用通用的?

1 个答案:

答案 0 :(得分:2)

据我所知,编译器在执行重载解析时总是优先于通用类型参数。因此,在test<T : P>(_ o: T)test(_ o: Any)之间的分辨率中 - 后者将是首选,因为它具有显式(尽管是抽象的)参数类型,而第一个仅仅是占位符。

因此,如果你使第二个重载也是通用的,那么编译器现在会支持第一个重载,因为它们都没有明确输入参数,但是第一个重载受到更严格的约束:

class Bar {
    func test<T: P>(_ o: T) {
        print("Generic", o.getValue())
    }

    func test<T>(_ o: T) {
        print("Any")
    }
}

let foo = Foo()
let bar = Bar()
bar.test(foo) // Generic hello

保持重载原样,为了消除歧义而进行的类型转换似乎也是一个可行的解决方案:

class Bar {
    func test<T: P>(_ o: T) {
        print("Generic", o.getValue())
    }

    func test(_ o: Any) {
        print("Any")
    }
}

let foo = Foo()
let bar = Bar()
(bar.test as (Foo) -> Void)(foo) // Generic hello

虽然我强烈推荐第一种方法,因为它可以让你更好地推断选择什么样的重载(一般情况下,泛型也应该优先于协议类型的参数,due to the performance benefits of specialisation)。