纯 swift 集协议对象
Pure swift set with protocol objects
有没有办法让下面的方法真正起作用?
V1 - “测试协议不符合 Hashable”
protocol testProtocol {
//
}
class test {
var s : Set<testProtocol>?
init(){
}
}
V2 - “协议 'testProtocol' 只能用作通用约束,因为它具有 Self 或关联类型要求
protocol testProtocol : Hashable {
//
}
class test {
var s : Set<testProtocol>?
init(){
}
}
我假设答案是否定的——因为协议(即使带有@objc 标签)没有足够的信息??但也许我在这里缺少某种线条或东西。
也许有更好的解决方案,但您可以使 class 通用:
protocol testProtocol : Hashable {
//
}
class test<P: testProtocol> {
var s : Set<P>?
init() { }
}
一种解决方案是将集合包装在 class 或结构中,并约束插入函数,使其只接受符合协议 和 的项目可散列的。然后,您可以在实现中使用 Set
of AnyHashable
。
例如:
protocol MyProtocol {
func doStuff()
}
class MyProtocolSet {
var set = Set<AnyHashable>()
func insert<T>(_ item: T) where T: MyProtocol, T: Hashable {
set.insert(AnyHashable(item))
}
func iterate( doing: (MyProtocol) -> Void ) {
for item in set {
doing(item as! MyProtocol)
}
}
}
struct Foo: MyProtocol, Hashable {
func doStuff() { print("foo") }
}
struct Bar: MyProtocol, Hashable {
func doStuff() { print("bar") }
}
func test() {
let set = MyProtocolSet()
set.insert(Foo())
set.insert(Bar())
set.iterate { (item: MyProtocol) in
item.doStuff()
}
}
通过对插入函数施加约束,你说的是 "this set has to contain things that conform to the protocol, and are hashable",但实际上并未将协议约束为可散列。
如果包装集 class 本身可以是通用的,并接受协议以符合,那就更好了,但我还没有想出这是否可能!
我知道这不是 Set
(就像所问的问题),但您可以使用 NSHashTable
而不是 Set
。不过,您必须将协议公开给 objc。虽然不是 Set
,但如果您只是想存储一组协议对象而不必遵守 Hashable
,这会起作用:
@objc protocol testProtocol { }
class Object {
var s: NSHashTable<testProtocol>!
}
这样您就可以使用提供的 add
和 remove
功能。
此外,如果您正在存储观察者或任何类似的东西,您可以使用 NSHashTable.weakObjects()
初始化散列 table,这将确保不会保留对象。
这里是关于 NSHashTable
的更多信息:https://developer.apple.com/documentation/foundation/nshashtable
有没有办法让下面的方法真正起作用?
V1 - “测试协议不符合 Hashable”
protocol testProtocol {
//
}
class test {
var s : Set<testProtocol>?
init(){
}
}
V2 - “协议 'testProtocol' 只能用作通用约束,因为它具有 Self 或关联类型要求
protocol testProtocol : Hashable {
//
}
class test {
var s : Set<testProtocol>?
init(){
}
}
我假设答案是否定的——因为协议(即使带有@objc 标签)没有足够的信息??但也许我在这里缺少某种线条或东西。
也许有更好的解决方案,但您可以使 class 通用:
protocol testProtocol : Hashable {
//
}
class test<P: testProtocol> {
var s : Set<P>?
init() { }
}
一种解决方案是将集合包装在 class 或结构中,并约束插入函数,使其只接受符合协议 和 的项目可散列的。然后,您可以在实现中使用 Set
of AnyHashable
。
例如:
protocol MyProtocol {
func doStuff()
}
class MyProtocolSet {
var set = Set<AnyHashable>()
func insert<T>(_ item: T) where T: MyProtocol, T: Hashable {
set.insert(AnyHashable(item))
}
func iterate( doing: (MyProtocol) -> Void ) {
for item in set {
doing(item as! MyProtocol)
}
}
}
struct Foo: MyProtocol, Hashable {
func doStuff() { print("foo") }
}
struct Bar: MyProtocol, Hashable {
func doStuff() { print("bar") }
}
func test() {
let set = MyProtocolSet()
set.insert(Foo())
set.insert(Bar())
set.iterate { (item: MyProtocol) in
item.doStuff()
}
}
通过对插入函数施加约束,你说的是 "this set has to contain things that conform to the protocol, and are hashable",但实际上并未将协议约束为可散列。
如果包装集 class 本身可以是通用的,并接受协议以符合,那就更好了,但我还没有想出这是否可能!
我知道这不是 Set
(就像所问的问题),但您可以使用 NSHashTable
而不是 Set
。不过,您必须将协议公开给 objc。虽然不是 Set
,但如果您只是想存储一组协议对象而不必遵守 Hashable
,这会起作用:
@objc protocol testProtocol { }
class Object {
var s: NSHashTable<testProtocol>!
}
这样您就可以使用提供的 add
和 remove
功能。
此外,如果您正在存储观察者或任何类似的东西,您可以使用 NSHashTable.weakObjects()
初始化散列 table,这将确保不会保留对象。
这里是关于 NSHashTable
的更多信息:https://developer.apple.com/documentation/foundation/nshashtable