I have the following protocol:
protocol MyProtocol {
var stringValue: String { get }
}
I also implemented it's methods for some classes and structures in extensions:
extension Int: MyProtocol {
var stringValue: String {
return "IntValue"
}
}
extension String: MyProtocol {
var stringValue: String {
return "StringValue"
}
}
extension Array: MyProtocol where Element == Dictionary<String, Any> {
var stringValue: String {
return "ArrayValue"
}
}
extension Dictionary: MyProtocol where Key == String, Value == Any {
var stringValue: String {
return "DictionaryValue"
}
}
When I tried to test it with the following code:
let dict = [["key":"value"]]
let stringValueResult = dict.stringValue
print(stringValueResult)
I received an error with text "[[String : String]]
is not convertible to Array<Dictionary<String, Any>>
". However my code works fine when I set type of the variable dict
like that:
let dict: Array<Dictionary<String, Any>> = [["key":"value"]]
Can someone explain me why the first version of my code is not compiling?
The reason for this error is the conflict between the dict
type inferred by the compiler and the one you mentioned while conforming Array
to your protocol
.
When you write this line
let dict = [["key":"value"]]
For compiler it will become as below where type is Array<Dictionary<String, String>>
let dict: Array<Dictionary<String, String>> = [["key":"value"]]
Now when you are doing dict.stringValue
, compiler will first match the type of the calling object i.e dict
with the type you defined during conformance of Array
with MyProtocol
As the compiler inferred type i.e, Array<Dictionary<String, String>>
is different than the type you mentioned in conformance i.e, Array<Dictionary<String, Any>>
so compiler throws error.
But when you declare dict
variable with explicit type i.e, Array<Dictionary<String, Any>>
same as you defined in conformance of MyProtocol
then compiler does not see any issue and your code works just fine.
While conforming Array/Dictionary
to MyProtocol
you can just ignore setting the Element
type as below,
extension Array: MyProtocol {
var stringValue: String {
return "ArrayValue"
}
}
extension Dictionary: MyProtocol {
var stringValue: String {
return "DictionaryValue"
}
}