protocol Container {
associatedtype ItemType
func getItem() -> ItemType
func getItems() -> [ItemType]
}
struct TypedBackpack<TypedItemType: StringProtocol>: Container {
func getItem() -> TypedItemType {
return ""
}
func getItems() -> [TypedItemType] {
return [""]
}
}
struct KeyBackpack<Key: Sequence>: Container {
func getItem() -> Key { //"Error: Cannot convert return expression of type 'String' to return type 'Key'"
return ""
}
func getItems() -> [Key] { //"Error: Cannot convert return expression of type 'String' to return type 'Key'"
return [""]
}
}
I got "Error: Cannot convert return expression of type 'String' to return type 'Key'" for "getItem()" and "getItems()" functions in KeyBackPack. However, TypedBackPack is working fine.
If I change KeyBackPack to:
struct KeyBackpack<Key: StringProtocol>: Container {
func getItem() -> Key {
return ""
}
func getItems() -> [Key] {
return [""]
}
}
Everything works fine. So the problem is "<Key: Sequence>". Can anybody tell me why <Key: StringProtocol> works fine but <Key: Sequence> doesn't?
According to your declarations, I am able to use any Sequence
as the type parameter of KeyBackpack
, and getItem
will return an instance of that type.
So in theory, I could do this:
let intArray = KeyBackpack<[Int]>().getItem()
[Int]
if obviously a Sequence
, and getItem
should give me an [Int]
. However, what getItem
actually returns, is an empty string! Clearly that does not make sense!
Why does Key: StringProtocol
work then?
This is because StringProtocol
inherits from ExpressibleByStringInterpolation
, which in turn inherits from ExpressibleByStringLiteral
.
This means that you can implicitly convert a string literal to Key
, because Key
conforms to ExpressibleByStringLiteral
.
In more concrete terms, StringProtocol
inherits the requirement init(stringLiteral:)
from ExpressibleByStringLiteral
, and the compiler automatically translates return ""
to a call to that initialiser. You can think of this as:
return Key(stringLiteral: "")
This also means that if you return something other than a string literal, Key: StringProtocol
would not have worked. e.g.
let s = "" // here the type of "s" is inferred to be String
return s // "cannot convert type..." error because "s" is not a string literal, nor of type "Key"