协议组成相同 属性

Procotol composition on the same property

有办法实现吗?

protocol VCProtocol1: UIViewController {
    var viewModel: VMProtocol1? { get set }
}

protocol VCProtocol2: UIViewController {
    var viewModel: VMProtocol2? { get set }
}

class VC: UIViewController, VCProtocol1, VCProtocol2 {
    var viewModel: (VMProtocol1 & VMProtocol2)?
}

我想做的是在 ViewController 上进行组合,以避免在多个 ViewController 中重新实现相同的代码。

编辑:

更准确地说,这里的问题是我希望我的 viewModel 属性 在两个协议之间共享,因为最终我想实现这样的东西:

- 查看模型

protocol VMProtocol1 {
    func vmTest1()
}

protocol VMProtocol2 {
    func vmTest2()
}

class ViewModel: VMProtocol1, VMProtocol2 {
    func vmTest1() { }
    func vmTest2() { }
}

- 视图控制器

protocol VCProtocol1: UIViewController {
    var viewModel: VMProtocol1 { get set }

    func vcTest1()
}

extension VCProtocol1 {
    func vcTest1() {
        // This is the key point, I want to be able to refer to my viewModel property internally in each protocol.
        self.viewModel.vmTest1() 
    }
}

protocol VCProtocol2: UIViewController {
    var viewModel: VMProtocol2 { get set }
}

class VC: UIViewController, VCProtocol1, VCProtocol2 {
    var viewModel: (VMProtocol1 & VMProtocol2)?
}

这实际上是不可能的。在 Swift.

中根本不可能实现声明相同 属性(这里 viewModel)但具有不同类型的多个协议的一个实体

最接近的做法是使用一种协议,将 viewModel 类型定义为关联类型并提供条件扩展(它将强制您使用通用实现)。

请注意,这是一个复杂的实现,需要对通用协议有很好的了解。我不建议在不完全了解你在做什么的情况下使用如此复杂的设计。

查看模型

protocol VMProtocol1 {
    func vmTest1()
}

protocol VMProtocol2 {
    func vmTest2()
}

class ViewModel: VMProtocol1, VMProtocol2 {
    func vmTest1() { }
    func vmTest2() { }
}

实施

protocol VCProtocolBase {
    associatedtype ViewModel
    var viewModel: ViewModel { get }
}

protocol VCProtocol1: VCProtocolBase {
    func vmTest1()
}

protocol VCProtocol2: VCProtocolBase {
    func vmTest2()
}

extension VCProtocolBase where Self: VCProtocol1, Self.ViewModel: VMProtocol1 {
    func vmTest1() {
        viewModel.vmTest1()
    }
}

extension VCProtocolBase where Self: VCProtocol2, Self.ViewModel: VMProtocol2 {
    func vmTest2() {
        viewModel.vmTest2()
    }
}


final class VC<ViewModel: VMProtocol1 & VMProtocol2>: VCProtocolBase, VCProtocol1, VCProtocol2 {
    var viewModel: ViewModel

    init(viewModel: ViewModel) {
        self.viewModel = viewModel
    }
}

VC(viewModel: ViewModel()).vmTest1()
VC(viewModel: ViewModel()).vmTest2()

这里的想法是依靠泛型和条件扩展来为VCProtocolX提供默认实现,这就是VCProtocolBase的作用。