How to call the more specific method of overloading

此生再无相见时 提交于 2019-12-19 19:49:17

问题


Here is an example playground:

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)

This outputs: Any.

If I remove the Any version of test, the generic method is called. Class Foo conforms to protocol P, why does Swift not pick the generic method since it is more specific? Is there a way to call the generic one?


回答1:


From what I understand, the compiler will always favour an explicitly typed parameter over a generic one when performing overload resolution. Thus in the resolution between test<T : P>(_ o: T) and test(_ o: Any) – the latter will be preferred as it has an explicit (albeit abstract) parameter type, whereas the first is merely a placeholder.

Therefore if you make the second overload generic as well, the compiler will now favour the first overload, as they both don't have explicitly typed parameters, but the first overload is more tightly constrained:

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

Keeping the overloads as-is, type-casting in order to disambiguate also appears to be a viable solution:

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

Although I would strongly recommend the first approach, as it allows you to reason better about what overload will be chosen (generics should also be preferred in general over protocol-typed parameters wherever possible, due to the performance benefits of specialisation).



来源:https://stackoverflow.com/questions/41531569/how-to-call-the-more-specific-method-of-overloading

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!