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).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…