如何使用关联类型协议作为函数的参数类型?

时间:2017-09-29 05:50:14

标签: ios swift xcode generics

这是我的简化代码:

class MyClass {
    func returnSomething(argument: Protocol2) {}
}

protocol Protocol2: Protocol1 where E == Int {
}

protocol Protocol1 {
    associatedtype E
    func doSomething(_ value: E)
}

编译器给出了以下错误:Protocol 'Protocol2' can only be used as a generic constraint because it has Self or associated type requirements

我知道在协议可以用作函数中的参数之前需要解析关联的类型E,但鉴于Protocol2提供了该信息,为什么我仍然无法编译该代码?

3 个答案:

答案 0 :(得分:3)

由于我正在学习Swift泛型,所以我想试一试:

如果要在函数Protocol2中使用returnSomething作为参数类型

正如@Nicolas Miari所建议的

class MyClass {
    func returnSomething<T: Protocol2>(argument: T) {}
}

现在顾名思义这个函数应该返回一些东西

所以

class MyClass {
    func returnSomething<T: Protocol2>(argument: T) -> T {
            return argument
    }
}

我在原始问题中看到的另一个问题是使用where子句

我想您想说Protocol1的相关类型是Int

你应该这样做

protocol Protocol2: Protocol1 {
      typealias E = Int

}

答案 1 :(得分:0)

  

&#34;如何使用关联类型协议作为函数的参数类型?&#34;

我可能不会按照您在此处提出的要求,但如果您的协议具有关联类型,例如

protocol DummyNumericTypeWrapper {
    associatedtype U: Numeric
    static func magic(_ bar: U) -> U
}

您可以访问此类型,例如在通用上下文中,通用占位符已被约束到您的协议。要使用完全虚拟的示例跟进上面的虚拟包装器,例如:

extension StupidNumericTypeWrapper where U == Int {
    static func magic(_ bar: Int) -> Int {
        return bar + 42
    }
}

func foo<T: StupidNumericTypeWrapper>(_ bar: T.U, _ _ : T.Type) -> T.U {
    return T.magic(bar) * T.magic(bar)
}

struct DefaultMagic: StupidNumericTypeWrapper { }

let num = foo(1, DefaultMagic.self)
print(num) // 1849  (43*43)

答案 2 :(得分:0)

Swift编译器将typealias转换为where子句。 (Typealias覆盖关联类型&#39; E&#39;来自协议&#39; Protocol1&#39;更好地表示为协议上的相同类型约束)

传递参数确实适用于上述语法,谢谢大家!

但是,如何返回符合Protocol2的实例?

class ClassConformsToProto2: Protocol2 {
    func doSomething(_ value: Int) {
}
}

class MyClass {
    func returnSomething<T: Protocol2>() -> T {
        return ClassConformsToProto2()
    }
}

此代码无效。

无法转换类型&#39; ClasConformsToProto2&#39;的返回表达式返回类型&#39; T&#39;