Как разрешить свойство generi c в протоколе со связанным типом? - PullRequest
0 голосов
/ 07 августа 2020

Идея состоит в том, чтобы использовать общий код между UITableView и UICollectionView и их моделями просмотра. Итак, у меня есть baseCollectionsViewModel, который является общим классом c и выглядит как

class BaseCollectionsViewModel<T: BasicTrackDataExtractorProtocol> {
    var baseTrackResponse: T?
    ...
}

. Теперь я хотел бы иметь BaseCollectionsView, который содержит BaseCollectionsViewModel. Поскольку это UITableView и UICollectionView, у меня не может быть общего базового класса среди них, поэтому я решил go в направлении протокола, чтобы обойти множественное наследование

protocol BaseCollectionsViewProtocol {
    associatedtype dataExtractorType: BasicTrackDataExtractorProtocol
    var viewModel: BaseCollectionsViewModel<dataExtractorType>! { get }
    //all other common properties and logic here
}

Наконец, когда я пытаюсь использовать этот протокол в моем последнем классе

final class TrackingTableViewModel: BaseCollectionsViewModel<TrackOrderV3> {
     
}

final class TrackingTableView: UITableView,BaseCollectionsViewProtocol {
    var viewModel: TrackingTableViewModel!
    typealias dataExtractorType = TrackOrderV3
    //other code
}

Компилятор жалуется, что TrackingTableView не подтверждает BaseCollectionsViewProtocol и продолжает добавлять

final class TrackingTableView: UITableView,BaseCollectionsViewProtocol {
    var viewModel: BaseCollectionsViewModel<TrackOrderV3>!
    typealias dataExtractorType = TrackOrderV3

Это потому, что BaseCollectionsViewModel<TrackOrderV3> и TrackingTableViewModel инвариантны? Есть ли способ решить эту проблему с помощью TypeErasure?

Если это не протокол, я мог бы решить его как

class TestTableView<T: BasicTrackDataExtractorProtocol, U: BaseCollectionsViewModel<T>> {
    var viewModel: U!
}

class TestTrackingTableView: TestTableView<TrackOrderV3, TrackingTableViewModel> {
    func testViewModel() {
        let _ = self.viewModel.numberOfRows
    }
}

Но проблема в том, что теперь я не могу сказать class TestTrackingTableView: TestTableView<TrackOrderV3, TrackingTableViewModel>, UITableView, потому что множественное наследование запрещено.

PS: Извините за очень запутанный заголовок, не смог придумать лучшего заголовка, изменится, если кто-то может предложить лучший :)

1 Ответ

2 голосов
/ 07 августа 2020

Что бы я сделал, так это определил протокол для вашей модели представления:

protocol CollectionsViewModel {
    associatedtype DataType: BasicTrackDataExtractorProtocol
    var baseTrackResponse: DataType? { get }
}

Затем реализовал общий c класс модели представления, который содержит все ваши общие логики c:

class BaseCollectionsViewModel<T: BasicTrackDataExtractorProtocol>: CollectionsViewModel {
    typealias DataType = T
    var baseTrackResponse: T?
}

Вместо того, чтобы устанавливать модель данных как ограничение типа для протокола представления, установите модель представления как ограничение типа. Это даст нам большую гибкость в будущем.

protocol BaseCollectionsViewProtocol {
    associatedtype ViewModelType: CollectionsViewModel
    var viewModel: ViewModelType! { get }
}

Теперь мы можем реализовать наши последние классы:

final class TrackingTableViewModel: BaseCollectionsViewModel<TrackOrderV3> {

}

final class TrackingTableView: UITableView, BaseCollectionsViewProtocol {
    var viewModel: TrackingTableViewModel!
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...