Swift 值具有关联类型时扩展字典

Swift 值具有关联类型时扩展字典,swift,Swift,考虑以下几点: struct Weak<Object: AnyObject> { weak var object: Object? } class ConcreteClass { } extension Dictionary where Value == Weak<AnyObject> { func foo() { print("Success!") } } var dict: [String: Weak<Concr

考虑以下几点:

struct Weak<Object: AnyObject> {

    weak var object: Object?
}

class ConcreteClass { }

extension Dictionary where Value == Weak<AnyObject> {

    func foo() {
        print("Success!")
    }
}

var dict: [String: Weak<ConcreteClass>] = [:]
struct弱{
弱var对象:对象?
}
类{}
值==弱的扩展字典{
func foo(){
打印(“成功!”)
}
}
变量dict:[字符串:弱]=[:]
现在,下一行将无法编译

dict.foo()  //  Referencing instance method 'foo()' on 'Dictionary' requires the types 'Weak<ConcreteClass>' and 'Weak<AnyObject>' be equivalent
dict.foo()//引用“Dictionary”上的实例方法“foo()”要求类型“弱”和“弱”等效

有没有一种方法可以告诉扩展名
弱.Object
foo()
执行它的工作并不重要?

问题是
是一种具体类型,您可以创建一个不同于
的实例。您需要通过协议上的
assoicatedtype
来表示关系

您可以像这样调整代码以达到预期的结果:

协议WeakProtocol{
associatedtype对象:AnyObject
var object:object?{get}//如果您认为合适,还可以添加set
}
结构弱:弱协议{
弱var对象:对象?
}
类{}
扩展字典,其中值:WeakProtocol{
func foo(){
打印(“成功!”)
}
}
变量dict:[字符串:弱]=[:]
傅先生()

这种方法的缺点是,您必须公开基本上复制结构的协议。

Swift的泛型是不变的,它指出,仅仅因为泛型类型包装子类,它不会使它成为包装其超类的泛型的子类型。你不能这样写:

struct Generic<T> {}
class Parent {}
class Child: Parent {}

func foo(generic: Generic<Parent>) {}

let childGeneric = Generic<Child>()
foo(generic: childGeneric) //Cannot convert value of type 'Generic<Child>' to expected argument type 'Generic<Parent>'
struct Generic{}
类父{}
类子级:父级{}
func-foo(泛型:泛型){}
让childGeneric=Generic()
foo(generic:childGeneric)//无法将类型为“generic”的值转换为预期的参数类型“generic”
但是Swift的内置泛型类型是协变的,这意味着泛型类型可以是其他泛型类型的子类型。例如,这是正确的:

class Parent {}
class Child: Parent {}

func foo(generic: Array<Parent>) {}

let childGeneric = Array<Child>()
foo(generic: childGeneric)
类父{}
类子级:父级{}
func-foo(泛型:数组){}
让childGeneric=Array()
foo(通用:儿童通用)

因此,经过一番修补,我找到了一个解决方案:

extension Dictionary {

    func foo<T: AnyObject>() where Value == Weak<T> {
        print("success")
    }
}
扩展字典{
func foo(),其中值==弱{
打印(“成功”)
}
}

这正是我在没有任何协议的情况下所需要的(正如@bscothern所建议的)。

对于基于参数化类型的泛型,没有替代原则。它们不是协变的。也许ConcreteClass是一个AnyObject,但您仍然不能在需要
的地方使用
。它们是不相关的类型。我使用您的解释为我的问题提供了一个代码片段。谢谢=)