在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
是的;這是一種將屬性轉換爲函數的簡單方法。儘管關於元素我不明白第二個問題。 –