如何确保相同的继承层次结构,例如对于 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
继承 ConcreteViewController1
和 ConcreteViewController2
,为 通用参数 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()
}
}
使用该解决方案,您可以获得类型安全,避免泛型并且不需要在任何地方进行转换。
我有一个基础 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
继承 ConcreteViewController1
和 ConcreteViewController2
,为 通用参数 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()
}
}
使用该解决方案,您可以获得类型安全,避免泛型并且不需要在任何地方进行转换。