在我的应用程序中,我有一些符合Collection的对象。我这样做是因为我得到了for循环语法和所有filter / map / etc方法。但我注意到它总是一样的。我有一个私人阵列,我只是转发电话。所以我想我会将Collection协议包装在另一个协议中,如下所示:
protocol CollectionTrait: Collection {
associatedtype CollectionType: Collection
var _items: CollectionType { get }
}
extension CollectionTrait {
var startIndex: CollectionType.Index {
return _items.startIndex
}
var endIndex: CollectionType.Index {
return _items.endIndex
}
func index(after i: CollectionType.Index) -> CollectionType.Index {
return _items.index(after: i)
}
subscript(index: CollectionType.Index) -> CollectionType.Element {
get {
return _items[index]
}
}
}
这可以使用如下:
class Words: CollectionTrait {
let _items = [
"foo", "bar", "baz"
]
}
let words = Words()
for word in words {
print(word)
}
我觉得这很好,我现在唯一的问题是_items需要公开,但我有点希望它是私密的,因为我更喜欢不要暴露它。所以现在我用下划线作为前缀,以表明它不应该被使用。有人知道强行这种行为的方法吗?或者通常是一种更好的方法来避免没有继承的代码重复(在我的情况下并不总是可行)
答案 0 :(得分:0)
如果您将代码拆分为多个文件,则可以将CollectionTrait
定义为private
协议并与fileprivate
一致。如果在一个文件中,您有:
private protocol CollectionTrait: Collection {
associatedtype CollectionType: Collection
var _items: CollectionType { get }
}
extension CollectionTrait {
var startIndex: CollectionType.Index {
return _items.startIndex
}
var endIndex: CollectionType.Index {
return _items.endIndex
}
func index(after i: CollectionType.Index) -> CollectionType.Index {
return _items.index(after: i)
}
subscript(index: CollectionType.Index) -> CollectionType.Element {
get {
return _items[index]
}
}
}
class Words: CollectionTrait {
fileprivate let _items = [
"foo", "bar", "baz"
]
}
在另一个文件中,如果您尝试使用Words
,则可以:
let words = Words()
for word in words {
print(word)
}
但尝试直接访问words._items
会出错,因为它是fileprivate
。