Swift 传递协议一致性

Swift transitive protocol conformance

有人可以解释为什么下面的例子不能编译吗?我是否遗漏了一些微不足道的东西?

protocol Coordinator {}

protocol Coordinatable {
    var coordinator: Coordinator { get set }
}

class ExampleCoordinator: Coordinator {}

class ViewController: UIViewController, Coordinatable {
    var coordinator: ExampleCoordinator!
}

错误是:

Type 'ViewController' does not conform to protocol 'Coordinatable'

谢谢!

var coordinator: ExampleCoordinator! 替换为 var coordinator: Coordinator。您正试图遵守 Coordinatable 因此您必须实现它的属性。

编辑:

import UIKit
protocol Coordinator {}

protocol Coordinatable {
    var coordinator: Coordinator { get set }
}

class ExampleCoordinator: Coordinator {}

class ViewController: UIViewController, Coordinatable {
    var coordinator: Coordinator

    init(coordinator: Coordinator) {
        self.coordinator = coordinator
        super.init(nibName: nil, bundle: nil)
    }

    // ignore this, it has nothing to do with the question/answer
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

let testVC = ViewController(coordinator: ExampleCoordinator()) // works

它不起作用的原因

假设您的代码可以工作并且我们另外编写

class ExampleCoordinator2: Coordinator {}

val viewController = ViewController()
viewController.coordinator = ExampleCoordinator2()

无法分配给 coordinator,因为 ExampleCoordinator2 不是 ExampleCoordinator 的子类。

因此,仅考虑类型,以下代码应该可以工作但Swift编译器不允许(这可能会在未来工作):

protocol Coordinatable {
    var coordinator: Coordinator { get } // removing the `set`
}

class ViewController: UIViewController, Coordinatable {
    var coordinator: ExampleCoordinator! // still an error
}

可能的解决方案

ViewController

中使用var coordinator: Coordinator
class ViewController: UIViewController, Coordinatable {

    var coordinator: Coordinator

    init(coordinator: Coordinator) {
        self.coordinator = coordinator
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Coordinatable

中仅使用{ get }
protocol Coordinatable {
    var coordinator: Coordinator { get } // removing the `set`
}

class ViewController: UIViewController, Coordinatable {
    // computed property
    var coordinator: Coordinator {
        // implicit return
        exampleCoordinator
    }
    var exampleCoordinator: ExampleCoordinator!
}

Coordinatable

中使用associatedtype
protocol Coordinatable {
    associatedtype C: Coordinator
    var coordinator: C { get set }
}

class ViewController: UIViewController, Coordinatable {
    
    var coordinator: ExampleCoordinator
    
    init(coordinator: ExampleCoordinator) {
        self.coordinator = coordinator
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

然而,这有一个 很大的缺点 ,因为 Coordinatable 有一个 associatedtype,所以你不能有一个类型为 [Coordinatable] 的异构数组。而且,您仍然不能分配 ExampleCoordinator2.

类型的值

您只能在 <C: Coordinatable> 上编写通用代码。例如

func printCoordinators<C: Coordinatable>(coordinatables: [C]) {
    
    coordinatables.forEach {
        print([=15=].coordinator)
    }
}