如何确保相同的继承层次结构,例如对于 MVVM

How to secure same inheritance hierarchies e.g. for MVVM

我有一个基础 ViewController 和一个基础 ViewModel。基础 ViewModel 由基础 ViewController 使用。另外,我有 2 个 ViewController 子类和 2 个 ViewModel 子类需要一起使用。

示例:

class BaseViewModel {
    func somethingBasic() {}
}

class ConcreteViewModel1: BaseViewModel {
    func somethingConcrete1() {}
}

class ConcreteViewModel2: BaseViewModel {
    func somethingConcrete2() {}
}

class BaseViewController {
    let viewModel: BaseViewModel

    init(with viewModel: BaseViewModel) {
        self.viewModel = viewModel
    }
}

class ConcreteViewController1: BaseViewController {
    init(with viewModel: ConcreteViewModel1) {
        super.init(with: viewModel)
    }

    func useViewModel() {
        viewModel.somethingBasic()
        viewModel.somethingConcrete1() //this does not work
    }
}

class ConcreteViewController2: BaseViewController {
    init(with viewModel: ConcreteViewModel2) {
        super.init(with: viewModel)
    }

    func useViewModel() {
        viewModel.somethingBasic()
        viewModel.somethingConcrete2() //this does not work
    }
}

问题是:使 viewmodel.somethingConcrete1()viewmodel.somethingConcrete2() 工作的首选解决方案是什么?

为此尝试使用 Generics

BaseViewController 中创建 init 接受 通用参数 T 约束类型 BaseViewModel,即

class BaseViewController<T: BaseViewModel> {
    let viewModel: T

    init(with viewModel: T) {
        self.viewModel = viewModel
    }
}

现在从 BaseViewController 继承 ConcreteViewController1ConcreteViewController2,为 通用参数 T 提供特定类型,即

class ConcreteViewController1: BaseViewController<ConcreteViewModel1> {
    func useViewModel() {
        viewModel.somethingBasic()
        viewModel.somethingConcrete1()
    }
}

class ConcreteViewController2: BaseViewController<ConcreteViewModel2> {
    func useViewModel() {
        viewModel.somethingBasic()
        viewModel.somethingConcrete2()
    }
}

我和其他几位同事讨论过这个问题,我们得出了这个解决方案,基于 Composition 而不是继承:

class BaseViewModel {
    func somethingBasic() {}
}

class ConcreteViewModel1 {
    private let baseViewModel = BaseViewModel()
    func somethingConcrete1() {}

    func somethingBasic() {
        baseViewModel.somethingBasic()
    }
}

class ConcreteViewModel2 {
    private let baseViewModel = BaseViewModel()
    func somethingConcrete2() {}

    func somethingBasic() {
        baseViewModel.somethingBasic()
    }
}

class BaseViewController {}

class ConcreteViewController1 {
    private let base = BaseViewController()
    private let viewModel: ConcreteViewModel1

    init(with viewModel: ConcreteViewModel1) {
        self.viewModel = viewModel
    }

    func useViewModel() {
        viewModel.somethingBasic()
        viewModel.somethingConcrete1()
    }
}

class ConcreteViewController2: BaseViewController {
    private let base = BaseViewController()
    private let viewModel: ConcreteViewModel2

    init(with viewModel: ConcreteViewModel2) {
        self.viewModel = viewModel
    }

    func useViewModel() {
        viewModel.somethingBasic()
        viewModel.somethingConcrete2()
    }
}

使用该解决方案,您可以获得类型安全,避免泛型并且不需要在任何地方进行转换。