Having an issue using a protocol with a default implementation (DefaultControllerPresentationProtocol down below). This protocol requires that a conforming object have a var that conforms to another protocol (ie Presentable) in order to provide the default implementation.
However, in practice, the class I want to conform to Presentable has a var that is defined as a different protocol type that conforms to Presentable rather than Presentable itself (ie. protocol ControllerOutputable: Presentable).
It seems the compiler doesn't like that the var is not explicitly Presentable but rather another protocol that conforms to presentable. Playground output is:
error: ProtocolCompilerError.playground:37:7: error: type 'Controller' does not conform to protocol 'DefaultControllerPresentationProtocol'
class Controller: ControllerProtocol {
^
ProtocolCompilerError.playground:39:7: note: candidate has non-matching type 'ControllerOutputable?'
var output: ControllerOutputable!
^
ProtocolCompilerError.playground:16:7: note: protocol requires property 'output' with type 'Presentable?'; do you want to add a stub?
var output: Presentable! { get set }
^
Is this a limitation of the compiler? Am I missing something obvious? Code below can be pasted into playgrounds to see the error
// We have a protocol to ensure our controllers can start a present
protocol ControllerPresentationProtocol {
func present()
}
// We have another protocol to ensure the output of the controller can perform presenting
protocol Presentable {
func presenting()
}
// Usually this implementation is the reused as long as the output conforms to Presentable
// therefore, we create a new protocol with a default implementation
protocol DefaultControllerPresentationProtocol: ControllerPresentationProtocol {
var output: Presentable! { get set }
}
extension DefaultControllerPresentationProtocol {
func present() {
output.presenting()
}
}
// As long as our `Controller` has an `output` that conforms to `Presentable`,
// we can add default implementation of `DefaultControllerPresentationProtocol`
protocol ControllerProtocol: DefaultControllerPresentationProtocol {
}
// Our controller output protocol conforms to Presentable
protocol ControllerOutputable: Presentable { }
// This is our class implementation of Controller conforming to ControllerProtocol
class Controller: ControllerProtocol { // Here we get a compiler error that says "error: type 'Controller' does not conform to protocol 'DefaultControllerPresentationProtocol'"
// The fix-it suggests adding a `var output: Presentable` although `ControllerOutputable` conforms to `Presentable`
var output: ControllerOutputable!
}
// This is our output implementation
class ControllerOutput: ControllerOutputable {
func presenting() {
print("presenting")
}
}
// Here we create the controller and its output
let controller = Controller()
controller.output = ControllerOutput()
controller.present() // This should print "presenting" but it fails to compile