在Swift 3,我希望能够创建一个协议,允许我添加元素和迭代通过使用for element in
。该协议应该可以在NSMutableSet
和NSMutableOrderedSet
上运行(因为它们不会从同一个类继承)。协议桥接NSMutableSet和NSMutableOrderedSet在一起
我知道有,为什么NSMutableSet
和NSMutableOrderedSet
不会从同一类继承好的理由,解释here和here。
但我想创建一个协议,只使用NSMutableSet
(和NSMutableOrderedSet
)内的所有方法的一小部分。
我得到只是add
工作,像这样:
protocol MutableSet {
func add(_ element: Any)
}
extension NSMutableSet: MutableSet {}
extension NSMutableOrderedSet: MutableSet {}
let one: NSString = "one"
let two: NSString = "two"
// Works if created with `NSMutableSet`
let mutableSet: MutableSet = NSMutableSet()
mutableSet.add(one)
mutableSet.add(two)
for element in mutableSet as! NSMutableSet {
print(element)
}
/*
This prints:
one
two
*/
// Also works if creating `NSMutableOrderedSet` instance
let mutableOrderedSet: MutableSet = NSMutableOrderedSet()
mutableOrderedSet.add(one)
mutableOrderedSet.add(two)
for element in mutableOrderedSet as! NSMutableOrderedSet {
print(element)
}
/*
This prints:
one
two
*/
不过我真的很喜欢能够通过元素迭代只需使用:
for element in mutableSet {
print(element)
}
我想使protocol MutableSet
符合Sequence
协议,这样的事情,但它不起作用:
protocol MutableSet: Sequence {
func add(_ element: Any)
}
extension NSMutableSet: MutableSet {
typealias Iterator = NSFastEnumerationIterator
typealias Element = NSObject // I dont know what to write here
typealias SubSequence = Slice<Set<NSObject>> // Neither here....
}
let one: NSString = "one"
let two: NSString = "two"
let mutableSet: MutableSet = NSMutableSet() // Compile Error: Protocol `MutableSet` can only be used as a generic constraint because it has Self or associated type requirements
mutableSet.add(one)
mutableSet.add(two)
for element in mutableSet { // Compile Error: Using `MutableSet` as a concrete type conforming to protocol `Sequence` is not supported
print(element)
}
是否可以使我的协议符合Sequence
?我应该怎么做?我尝试过typealias
和associatedtype
的Element
,Iterator
等的各种组合。我也试过this answer它不适合我。
编辑2:答案我自己的问题在EDIT 1
我var count: Int { get }
使用此解决方案的工作,不知道这是否是虽然最好的一个...也将是不错的不必在NSMutableSet
和NSMutableOrderedSet
,的扩展中实现var elements: [Any] { get }
,但我想这是不可避免的?
protocol MutableSet: Sequence {
subscript(position: Int) -> Any { get }
func add(_ element: Any)
var count: Int { get }
var elements: [Any] { get }
}
extension MutableSet {
subscript(position: Int) -> Any {
return elements[position]
}
}
extension NSMutableSet: MutableSet {
var elements: [Any] {
return allObjects
}
}
extension NSMutableOrderedSet: MutableSet {
var elements: [Any] {
return array
}
}
struct AnyMutableSet<Element>: MutableSet {
private let _add: (Any) ->()
private let _makeIterator:() -> AnyIterator<Element>
private var _getElements:() -> [Any]
private var _getCount:() -> Int
func add(_ element: Any) { _add(element) }
func makeIterator() -> AnyIterator<Element> { return _makeIterator() }
var count: Int { return _getCount() }
var elements: [Any] { return _getElements() }
init<MS: MutableSet>(_ ms: MS) where MS.Iterator.Element == Element {
_add = ms.add
_makeIterator = { AnyIterator(ms.makeIterator()) }
_getElements = { ms.elements }
_getCount = { ms.count }
}
}
let one: NSString = "one"
let two: NSString = "two"
let mutableSet: AnyMutableSet<Any>
let someCondition = true
if someCondition {
mutableSet = AnyMutableSet(NSMutableSet())
} else {
mutableSet = AnyMutableSet(NSMutableOrderedSet())
}
mutableSet.add(one)
mutableSet.add(two)
for i in 0..<mutableSet.count {
print("Element[\(i)] == \(mutableSet[i])")
}
// Prints:
// Element[0] == one
// Element[1] == two
编辑1:跟进问题 使用优秀的答案被@抢劫,纳皮尔与type erasure
技术我已经扩展了protocol MutableSet
有count
,也subscript
能力,但我是唯一能够做到所以使用func
(名为getCount
)这是丑陋的,而不是var
。这是我在用的:
protocol MutableSet: Sequence {
subscript(position: Int) -> Any { get }
func getCount() -> Int
func add(_ element: Any)
func getElements() -> [Any]
}
extension MutableSet {
subscript(position: Int) -> Any {
return getElements()[position]
}
}
extension NSMutableSet: MutableSet {
func getCount() -> Int {
return count
}
func getElements() -> [Any] {
return allObjects
}
}
extension NSMutableOrderedSet: MutableSet {
func getElements() -> [Any] {
return array
}
func getCount() -> Int {
return count
}
}
struct AnyMutableSet<Element>: MutableSet {
private var _getCount:() -> Int
private var _getElements:() -> [Any]
private let _add: (Any) ->()
private let _makeIterator:() -> AnyIterator<Element>
func getElements() -> [Any] { return _getElements() }
func add(_ element: Any) { _add(element) }
func makeIterator() -> AnyIterator<Element> { return _makeIterator() }
func getCount() -> Int { return _getCount() }
init<MS: MutableSet>(_ ms: MS) where MS.Iterator.Element == Element {
_add = ms.add
_makeIterator = { AnyIterator(ms.makeIterator()) }
_getElements = ms.getElements
_getCount = ms.getCount
}
}
let one: NSString = "one"
let two: NSString = "two"
let mutableSet: AnyMutableSet<Any>
let someCondition = true
if someCondition {
mutableSet = AnyMutableSet(NSMutableSet())
} else {
mutableSet = AnyMutableSet(NSMutableOrderedSet())
}
mutableSet.add(one)
mutableSet.add(two)
for i in 0..<mutableSet.getCount() {
print("Element[\(i)] == \(mutableSet[i])")
}
// Prints:
// Element[0] == one
// Element[1] == two
我怎样才能得到它只有在协议var count: Int { get }
和var elements: [Any]
工作,而不是功能?
'_getCount = {ms.count}' –
谢谢!是的,我使用过,看到我的编辑2,就是这样的解决方案!嗯...那么解决方案呢?用封闭包装...(方法签名) – Sajjon
是的;这是一种将属性转换为函数的简单方法。尽管关于元素我不明白第二个问题。 –