Hi! I have kind of design question about generics which use protocol with default implementation of functions. Assume I have such a common design pattern used a lot in Swift.
protocol SomeProtocol {}
extension SomeProtocol {
func function() {
print("protocol")
}
}
class SomeClass: SomeProtocol {
func function() {
print("class")
}
}
In this case I can choose which implementation of function() will be used by declaring type of variables.
let protocolVar: SomeProtocol = SomeClass()
let classVar = SomeClass()
protocolVar.function() // prints "protocol"
classVar.function() // prints "class"
But when I use generic function I always receive protocol implementation. For example, I have two functions:
func basicFunction(_ parameter: SomeProtocol) {
parameter.function()
}
func genericFunction<T: SomeProtocol>(_ parameter: T) {
parameter.function()
}
In first case (with basicFunction()) I tell the compiler that I want to use protocol implementation of function(), so behaviour for classVar and protocolVar are expected:
basicFunction(protocolVar) // prints "protocol"
basicFunction(classVar) // prints "protocol"
In second case (with genericFunction() I tell the compiler that this function will only work with specific type which implements certain protocol. That's why I receive compile error when trying to pass protocolVar to genericFunction()
genericFunction(protocolVar) // compile error: Cannot invoke 'genericFunction' with an argument list of type '(parameter: SomeProtocol)'
But when I use genericFunction() with classVar I receive protocol behaviour
genericFunction(classVar) // prints "protocol"
It's a little bit confusing since compiler doesn't allow me to pass protocolVar to genericFunction() and that's OK. But if I pass variable with appropriate type (class) I receive not this type behaviour but protocol one.
Of course, I can receive class behaviour of function() if I'll declare func function() in protocol body, so every class which implements this protocol require to have it's own implementation. But in such a case I'm not able to receive default protocol implementation of function().
So my suggestion is to use type implementation in generic functions and if this function is not implemented in type declaration use default implementation from protocol extension. It will make generics more flexible as for me.
What do you think? Maybe I'm missing something?
And sorry if such a suggestion was already discussed here, I've tried to find ;)
I've added all the code from this proposal to Playground here.