带有协议对象的纯swift集
有没有一种方法可以使以下各项真正起作用 V1-“测试协议不符合哈希表”带有协议对象的纯swift集,swift,set,protocols,Swift,Set,Protocols,有没有一种方法可以使以下各项真正起作用 V1-“测试协议不符合哈希表” 协议测试协议{ // } 课堂测试{ var s:设置? init(){ } } V2-“协议“testProtocol”只能用作一般约束,因为它具有自身或关联的类型要求 协议testProtocol:Hashable{ // } 课堂测试{ var s:设置? init(){ } } 我假设答案是否定的——因为协议(即使带有@objc标记)没有足够的信息??但可能我在这里遗漏了一些行或东西。也许有更好的解决方案,但您可
协议测试协议{
//
}
课堂测试{
var s:设置?
init(){
}
}
V2-“协议“testProtocol”只能用作一般约束,因为它具有自身或关联的类型要求
协议testProtocol:Hashable{
//
}
课堂测试{
var s:设置?
init(){
}
}
我假设答案是否定的——因为协议(即使带有@objc标记)没有足够的信息??但可能我在这里遗漏了一些行或东西。也许有更好的解决方案,但您可以将类设置为泛型:
protocol testProtocol : Hashable {
//
}
class test<P: testProtocol> {
var s : Set<P>?
init() { }
}
协议testProtocol:Hashable{
//
}
课堂测试{
变量s:设置?
init(){}
}
一种解决方案是将集合包装在一个类或结构中,并约束插入函数,使其仅接受符合您的协议且可哈希的项。然后,您可以在实现中使用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()
}
}
协议MyProtocol{
func doStuff()
}
类MyProtocolSet{
var set=set()
func insert(uitem:T),其中T:MyProtocol,T:Hashable{
set.insert(任意散列(项目))
}
func迭代(执行:(MyProtocol)->Void){
对于集合中的项目{
正在执行(项目为!MyProtocol)
}
}
}
struct Foo:MyProtocol,可哈希{
func doStuff(){print(“foo”)}
}
结构栏:MyProtocol,可哈希{
func doStuff(){print(“bar”)}
}
func测试(){
let set=MyProtocolSet()
set.insert(Foo())
set.insert(Bar())
set.iterate{(项:MyProtocol)在
项目.doStuff()
}
}
通过对插入函数施加约束,您可以说“这个集合必须包含符合协议的内容,并且是可散列的”,而不是实际将协议约束为可散列的
如果包装集类本身可以是泛型的,并接受协议来遵循,那就更好了,但我还没有弄清楚这是否可行!我知道这不是一个集(就像所问的问题),但您可以使用NSHashTable
而不是集
。不过,您必须向objc公开您的协议。虽然不是集
,但如果您只是希望存储协议对象的集合,而不必遵守哈希表
,这将起作用:
@objc protocol testProtocol { }
class Object {
var s: NSHashTable<testProtocol>!
}
@objc协议testProtocol{}
类对象{
var s:那是一张桌子!
}
这样,您就可以使用提供的添加
和删除
功能
此外,如果您正在存储观察者或任何类似内容,则可以使用NSHashTable.weakObjects()
初始化哈希表,这将确保不会保留对象
以下是有关NSHashTable
:的更多信息,但这意味着您的集合的对象都需要共享一个类(或超类),这意味着您添加了另一个要求。这是否意味着您不能在Swift中创建仅受协议一致性约束的集合
?@Zack:问题是Hashable继承自具有“自我要求”的可平等协议,在这种情况下,运算符func==(lhs:Self,rhs:Self)->Bool
。是的,我知道这一点。虽然我个人认为,在2.0的语言设计中,让均衡化要求您比较的两个项目具有相同的类层次结构是一个错误。我在苹果的Swift开发论坛上问过这个问题,希望他们会有一个建议,而不是分叉均衡uatable
、Hashable
和Set
允许比较不同类层次结构的项。@扎克:我无法判断这是否是一个好的设计决策。或许可以看看“面向协议的Swift编程”“WWDC会议视频,其中解释了这背后的基本原理。我实际上是在会议室里:DThanks!!!它真的帮助了我。我只是不强迫演员们去做(项目为!MyProtocol)。干杯
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()
}
}
@objc protocol testProtocol { }
class Object {
var s: NSHashTable<testProtocol>!
}