【发布时间】:2018-08-16 15:00:20
【问题描述】:
我正在尝试实现具有关联类型的数据源协议
protocol DataSourceCompatible {
associatedtype CellModel
func cellModelForItem(at indexPath: IndexPath) -> CellModel
}
协议AddressBookViewModelType 继承自基本协议并将关联的值约束到另一个协议
protocol AddressBookViewModelType: class, DataSourceCompatible where CellModel == AddressBookCellModelType {
}
AddressBookViewModel是AddressBookViewModelType协议的具体实现
class AddressBookViewModel: AddressBookViewModelType {
func cellModelForItem(at indexPath: IndexPath) -> AddressBookCellModelType {
let contact = sectionedContacts[indexPath.section][indexPath.row]
return AddressBookCellModel(contact: contact)
}
}
代码编译得很好,但是当我将视图模型声明为视图控制器上的属性时,编译器会失败并显示Protocol 'AddressBookViewModelType' can only be used as a generic constraint because it has Self or associated type requirements。
class AddressBookViewController: UIViewController {
private var viewModel: AddressBookViewModelType!
func configure(viewModel: AddressBookViewModelType) {
self.viewModel = viewModel
}
...
}
我记得看到类型擦除可能会解决问题,但我对类型擦除概念并不熟悉。有没有办法解决这个问题?
更新:
AddressBookCellModelType 和 AddressBookCellModel 在这里是如何关联的?
这是一个实现协议的结构体。
protocol AddressBookCellModelType {
var name: String { get }
var photo: UIImage? { get }
var isInvited: Bool { get }
}
struct AddressBookCellModel: AddressBookCellModelType {
....
}
【问题讨论】:
-
这是一个非常复杂的协议使用。混合类继承、协议继承和 PAT 充满了极端情况和惊喜。您是否期望 AddressBookViewModelType 的多个实现?如果没有,首先减少协议的数量并消除尽可能多的 PAT,并专注于泛型,或者如果您实际上不涉及多种类型,则只关注简单的非泛型代码。主动让 Swift 变得高度通用(即在你对它有明确要求之前)充满了锋利的边缘。
-
AddressBookCellModelType和AddressBookCellModel在这里有什么关系?那肯定感觉像是在滥用协议(试图使用协议来重新创建类继承,这不是他们的意图)。 -
@RobNapier,请查看问题的更新
-
AddressBookCellModelType在您的代码中提供什么用途?实现是什么样的?它使您付出了很多复杂性,并且很难想象它提供了什么好处。这感觉就像一个纯粹为了避免具体类型而存在的协议,这总是一个错误。一个简单的结构是一个非常好的类型。
标签: swift generics swift-protocols associated-types