我有一个协议,它的属性是另一个协议。我有一些实现该协议的结构,我对它们很满意。但是,我想要一个协议数组,但指定内部协议始终是特定类型。
如果我展示一些示例代码可能会更容易:
protocol MyCategory {
var displayTitle: String {get}
}
enum Category1: MyCategory {
case person
case place
case thing
var displayTitle: String {
switch self {
...
}
}
}
enum Category2: MyCategory {
case animal
case vegetable
case mineral
var displayTitle: String {
switch self {
...
}
}
}
protocol FieldModel {
var category: MyCategory { get }
var name: String { get }
}
struct IntFieldModel: FieldModel {
let category: MyCategory
let name: String
let value: Int
}
struct StringFieldModel: FieldModel {
let category: MyCategory
let name: String
let value: String
}
struct Category1ConsolidatedResults {
let fields: [FieldModel]
}
我希望能够告诉
Category1ConsolidatedResults
fields
中的每个项目都属于 FieldModel
类型,而且每个 category
中的每个 FieldModel
都属于 Category1
类型。
我尝试使用泛型和
associatedtype
做一些事情,但我不知道如何将类型传递到 FieldModel
中的 Category1ConsolidatedResults
协议中。相反,我收到错误“使用协议‘FieldModel’作为类型必须写成‘any FieldModel’”。
有没有办法将类型传递给通用协议?
在这种情况下尝试使用
associatedtype
时,你是对的。但是,我相信您缺少对 Category1ConsolidatedResults
的限制。你可以尝试这个方法:
protocol FieldModel {
associatedtype Category: MyCategory //<- here
var category: Category { get }
var name: String { get }
}
然后在这些 Field 模型实现上添加通用约束:
struct IntFieldModel<Category: MyCategory>: FieldModel {
let category: Category
let name: String
let value: Int
}
...
最后,
Category1ConsolidatedResults
需要所有fields
是FieldModel
并且MyCategory
是Category1
。
struct Category1ConsolidatedResults<T: FieldModel> where T.Category == Category1 {
let fields: [T]
}
现在您可以在定义时将
Category1ConsolidatedResults
与 Category1
联系起来。
let result = Category1ConsolidatedResults<IntFieldModel<Category1>>(fields: [
.init(category: Category1.person, name: "", value: 1),
...
])