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

Arn*_*nol 5 generics overloading swift

这是一个示例游乐场:

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)
Run Code Online (Sandbox Code Playgroud)

这输出:Any.

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

Ham*_*ish 3

据我了解,在执行重载解析时,编译器总是倾向于使用显式类型参数而不是泛型参数。test<T : P>(_ o: T)因此,在和\xe2\x80\x93之间的解析中,test(_ o: Any)后者将是首选,因为它具有显式(尽管是抽象)参数类型,而第一个只是占位符。

\n\n

因此,如果您也将第二个重载设为泛型,编译器现在将支持第一个重载,因为它们都没有显式类型化参数,但第一个重载受到更严格的约束:

\n\n
class Bar {\n    func test<T: P>(_ o: T) {\n        print("Generic", o.getValue())\n    }\n\n    func test<T>(_ o: T) {\n        print("Any")\n    }\n}\n\nlet foo = Foo()\nlet bar = Bar()\nbar.test(foo) // Generic hello\n
Run Code Online (Sandbox Code Playgroud)\n\n

保持重载不变,通过类型转换来消除歧义似乎也是一个可行的解决方案:

\n\n
class Bar {\n    func test<T: P>(_ o: T) {\n        print("Generic", o.getValue())\n    }\n\n    func test(_ o: Any) {\n        print("Any")\n    }\n}\n\nlet foo = Foo()\nlet bar = Bar()\n(bar.test as (Foo) -> Void)(foo) // Generic hello\n
Run Code Online (Sandbox Code Playgroud)\n\n

尽管我强烈推荐第一种方法,因为它可以让您更好地推断将选择什么重载(由于专业化的性能优势,通常也应该尽可能优先于协议类型参数)。

\n