【问题标题】:How to use associated type protocol as argument's type to a function?如何使用关联类型协议作为函数的参数类型?
【发布时间】:2017-09-29 05:50:13
【问题描述】:

这是我的简化代码:

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 提供了该信息,为什么我仍然无法编译该代码?

【问题讨论】:

  • 我认为正确的语法是func returnSomething<T: Protocol2>(argument: T)?
  • @NicolasMiari 谢谢!

标签: ios swift xcode generics


【解决方案1】:

由于我正在学习 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

}

【讨论】:

  • 谢谢!我想知道您将如何返回符合 Protocol2 的类的实例?而是只返回已经传入的内容。
  • @damian 我认为您需要向下转换为T,因此您可以执行以下操作:return ClassConformsToProto2() as! T 如果您不想强制向下转换,那么您可以执行return ClassConformsToProto2() as? T 然后更改返回类型为T?,你应该删除你的答案,因为我认为这是一个单独的问题,你最好问一个单独的问题,这样更多的人将能够帮助你。谢谢
【解决方案2】:

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

我可能没有按照您在此处询问的内容,但如果您的协议具有关联类型,例如

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)

【讨论】:

    【解决方案3】:

    Swift 编译器将我的typealias 转换为where 子句。 (从协议“Protocol1”覆盖关联类型“E”的 Typealias 更好地表示为协议上的相同类型约束)

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

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

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

    此代码不起作用。

    无法将“ClasConformsToProto2”类型的返回表达式转换为“T”类型

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多