I have two interfaces Controllerable
and Interactorable
which should work together to achieve something. Following are the protocols:
protocol Controllerable {
associatedtype Job: Decodable
func getJob() -> Job
func control(job: Job)
}
protocol Interactorable {
associatedtype Job: Decodable
func interact() -> Job
}
Here are the concrete types which conform to above protocols:
One thing to note here, Controller
has an Interactor
dependency to make things work.
struct ActualJob: Decodable {
var id: String
}
class Controller<I: Interactorable>: Controllerable {
typealias Job = ActualJob
private var interactor: I
init(interactor: I) {
self.interactor = interactor
}
// MARK: Controllerable
func control(job: ActualJob) {
print("Controlling job: \(job.id)")
}
func getJob() -> ActualJob {
return interactor.interact() //***** Line of contention ****
}
}
class Interactor: Interactorable {
typealias Job = ActualJob
// MARK: Interactorable
func interact() -> Job {
return ActualJob(id: "xyz")
}
}
Now, let's say there's a driver entity which drives the integration.
struct Someguy<C: Controllerable> {
private var controller: C
init(controller: C) {
self.controller = controller
}
func doSomething() {
let job = controller.getJob()
controller.control(job: job)
}
}
If you put all of this in the playground, you'd the see the following in the console:
playground:30:27: error: cannot convert return expression of type 'I.Job' to return type 'ActualJob'
return interactor.interact()
~~~~~~~~~~~^~~~~~~~~~
as! ActualJob
So, the question is, why, if Interactable.Job
and Controllerable.Job
conform to the same types, should one get the above error?
EDIT If I change the line of contention to
return interactor.interact() as! ActualJob
The error goes away, but why should this be needed? Does it not defeat the purpose of protocols?
Just add a constraint:
class Controller<I: Interactorable>: Controllerable where I.Job == ActualJob {
Without the constraint, I.Job
can be anything, can't it? It could be SomeOtherJob
, which is not convertible to ActualJob
.