Reputation: 763
I have the following contrived example:
protocol Fooable { }
extension Int: Fooable { }
extension Double: Fooable { }
extension Bool: Fooable { }
func go(value: Any, type: Fooable.Type) -> String {
return "Fooable"
}
func go(value: Any, type: Int.Type) -> String {
return "Int"
}
func go(value: Any, type: Double.Type) -> String {
return "Double"
}
let value1 = 1
go(value: value1, type: type(of: value1)) // Returns "Int"
let value2 = 2.0
go(value: value2, type: type(of: value2)) // Returns "Double"
let value3 = true
go(value: value3, type: type(of: value3)) // Returns "Fooable"
This is the behavior I ultimately want, but what sets this precedence? The more generic, first function can be placed anywhere in the code, giving the same results, so there must be some sort of precedence rules.
Is this outlined anywhere?
Upvotes: 1
Views: 393
Reputation: 271355
The keyword here is "specific". Swift always finds the most specific overload to call.
Swift first infers that value1
is of type Int
, so type(of: value1)
is of type Int.Type
.
Now we've got a Int.Type
as the parameter, Swift looks for an overload that accepts one parameter whose type is exactly Int.Type
. It finds one and calls that. The one that accepts a Fooable.Type
is not called because it can already call a more specific one that accepts exactly a Int.Type
. Here, "specific" means lower down the type hierarchy. Int
is considered more specific than Fooable
because Int
conforms to Fooable
.
value3
is inferred to be of type Bool.Type
. There is not overload that accepts a Bool.Type
, so Swift has to look up the type hierarchy and finds the one that accepts a Fooable.Type
. This is the most specific type that you can pass a Bool.Type
into.
Upvotes: 3