我通常会实现行为类似于数组的类型,比如这个:
struct Dataset: RandomAccessCollection {
let ids: [Int]
// Other properties and methods...
// Boilerplate
var startIndex: Int { ids.startIndex }
var endIndex: Int { ids.endIndex }
func formIndex(after i: inout Int) { i += 1 }
func formIndex(before i: inout Int) { i -= 1 }
subscript(index: Int) -> Int {
// Dummy example, could be more complex and return a different type
return ids[index]
}
}
问题在于每次我需要编写很多样板代码以符合
RandomAccessCollection
的要求。我想要一个协议或机制来将这些样板代码减少到一两个要求:
- 一个基础的
RandomAccessCollection
(就像我示例中的ids
属性)用于推断协议要求(startIndex
、endIndex
、formIndex
) - 一个下标操作符,可以完成其余要求
这种机制类似于目前在Pytorch中进行数据集继承的方式:只有一个__len__
和__getitem__
要求。
我提出了一个类似于以下草案:
protocol ArrayProtocol: RandomAccessCollection where Index == BaseCollection.Index {
associatedtype BaseCollection: RandomAccessCollection
var baseCollection: BaseCollection { get set }
subscript(index: Index) -> Element { get set }
}
// Provide the default implementation of the RandomAccessCollection protocol
extension ArrayProtocol {
var startIndex: Index { baseCollection.startIndex }
var endIndex: Index { baseCollection.endIndex }
func formIndex(after i: inout Index) { baseCollection.index(after: i) }
func formIndex(before i: inout Index) { baseCollection.index(before: i) }
}
此协议将会如下使用:
struct Dataset: ArrayProtocol {
let ids: [Int]
// Other properties and methods...
// No more boilerplate
var baseCollection: [Int] { ids }
subscript(index: Int) -> Int {
// Dummy example, could be more complex and return a different type
return ids[index]
}
}
但是我找不到使其工作的方法,而且我感觉相关联的类型并不是一个很好的设计模式。
有什么解决办法吗?
编辑: where Index == BaseCollection.Index
子句不是必需的,下标可以具有与底层集合不同的Index
类型。
BaseCollection = [Int]
。谢谢! - Louis Lac