Suppose I have a protocol:
protocol MSGameTrigger {
var event: MSGameEvent { get }
var conditions: [MSGameCondition] { get }
var actions: [MSGameAction] { get }
}
Which is implemented by >1 structures:
struct MSFlexibleGameTrigger: MSGameTrigger {
let event: MSGameEvent
let conditions: [MSGameCondition]
let actions: [MSGameAction]
}
struct MSWinGameTrigger: MSGameTrigger {
let event: MSGameEvent
let conditions: [MSGameCondition]
let actions: [MSGameAction] = [MSWinGameAction()]
}
And there is an array extension:
extension Collection where Element: MSGameTrigger {
var totalConditions: [MSGameCondition] {
let conditions = reduce([MSGameCondition]()) { (partialConds, trigger) in
partialConds + trigger.conditions
}
return conditions
}
}
Now I'm mixing triggers together:
let winTriggers: [MSWinGameTrigger]
let otherTriggers: [MSFlexibleGameTrigger]
let differentTriggers = winTriggers as [MSGameTrigger] + otherTriggers as [MSGameTrigger]
And I can't apply the extension!
let conditions = differentTriggers.totalConditions
Using 'MSGameTrigger' as a concrete type conforming to protocol 'MSGameTrigger' is not supported
And if edit the extension definition by replacing :
with ==
, it will not work, in other cases, for example:
let winConditions = winTriggers.totalConditions
Expression type '[MSGameCondition]' is ambiguous without more context
To fix it you need to explicitly cast to more generic type. There is even no !
or ?
before as
operator, but you still need to cast. I guess it's dumb.
Logically, the Collection where Element: MSGameTrigger
extension should work. Any instance of MSGameTrigger
has conditions
array inside. I see no problem here. Program should be able to iterate through triggers and grab their conditions. The reason why it doesn't work is the fakeness of Swift abilities. On paper it has generics and shit, but in practice it's don't.
P.S.
Its a very common problem of Swift actually. It pretends to be the best possible programming language, I even seen a "research" comparing different languages by features. Swift had almost everything, while other languages like C#, Java, Haskell were behind. But in reality Swift has a lot of dumb practical limitations when you can't implement things which are supposed to be common, like the one in question or an array of weak delegates, for example. This eventually will kill Swift, believe me.