【问题标题】:Swift why doesn't my generator protocol extension work?Swift 为什么我的生成器协议扩展不起作用?
【发布时间】:2016-03-08 22:35:26
【问题描述】:

我认为我对 Swift 类型/协议/泛型的认知已经溢出。我一直在使用扩展“输入流字节”的模式,方法是:

extension GeneratorType where Element == UInt8 {
    func foobar()  {
        ...
    }
}

过去它适用于简单的东西。今天我正在玩以下内容:

protocol Unpackable {
    static func unpack(inout input:IndexingGenerator<[UInt8]>) -> Self
}

extension UInt8:Unpackable {
    static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt8 {
        return input.next()!
    }
}

extension UInt16:Unpackable {
    static func unpack(inout input:IndexingGenerator<[UInt8]>) -> UInt16 {
        return UInt16(input.next()!) | (UInt16(input.next()!) << 8)
    }
}

工作正常。但是,如果我尝试将两者与类似的东西放在一起

extension GeneratorType where Element == UInt8 {
    func unpackAll() -> (UInt8, UInt16) {
        return (UInt8.unpack(&self), UInt16.unpack(&self))
}

然后我收到以下错误:

Cannot convert value of type 'Self' to expected argument type 'IndexingGenerator<[UInt8]>'

IndexingGenerator 不符合 GeneratorType 吗?它的元素不是 UInt8 吗?是使用 IndexingGenerator 的错误吗?我无法将参数类型指定为 GeneratorType(尽管我真的很想这样做)。

我仍在等待 Swift 类型的灯泡闪烁。有些日子我真的很喜欢这种语言。其他时候,我觉得我在对我的狗大喊大叫,试图让他过来,他只是盯着我一动不动,然后转身沿着街追。

【问题讨论】:

  • “IndexingGenerator 不符合 GeneratorType” 是的,但不是每个 GeneratorType 都是 IndexingGenerator。
  • 我提出IndexingGenerator&lt;[UInt8]&gt; 的论点只是因为我不知道如何更通用地做到这一点。老实说,我不在乎它是一个 IndexingGenerator。我可以使用任何类型的生成器,只要它生成 UInt8。有没有办法让参数成为适当规范的协议?
  • 声明一个符合GeneratorType 的new 协议并以某种方式限制符合类型以具有UInt8 的元素的技巧吗?
  • 解决方案与 AnyGenerator 有关系吗?

标签: swift swift-extensions swift-protocols


【解决方案1】:

试试这个:

extension GeneratorType where Element == UInt8 {
    func unpackAll() -> (UInt8, UInt16)? {
        guard let _self = self as? IndexingGenerator<[Element]> else { return nil }
        var vSelf = _self
        return (UInt8.unpack(&vSelf), UInt16.unpack(&vSelf))
    }
}

更新:

protocol Unpackable {
    static func unpack<T : GeneratorType where T.Element == UInt8>(inout input:T) -> Self
}

extension UInt8: Unpackable {
    static func unpack<T : GeneratorType where T.Element == UInt8>(inout input: T) -> UInt8 {
        return input.next()!
    }
}

extension UInt16: Unpackable {
    static func unpack<T : GeneratorType where T.Element == UInt8>(inout input: T) -> UInt16 {
        return UInt16(input.next()!) | (UInt16(input.next()!) << 8)
    }
}

extension GeneratorType where Element == UInt8 {
    mutating func unpackAll() -> (UInt8, UInt16) {
        return (UInt8.unpack(&self), UInt16.unpack(&self))
    }
}

【讨论】:

  • 可以说guard var vSelf 并缩短一行:)
  • @matt 哈哈。老实说,我从不使用var 和guard,而且我认为我做不到!我是多么愚蠢......谢谢你的提示。
  • 这迫使我将返回类型包装为可选项。不是世界末日,但不是我想要的。我试图缩小必须使用协议来扩展泛型与必须将泛型作为参数类型传递之间的差距。
  • @TravisGriggs 虽然我仍然无法弄清楚您到底想要什么,但请查看我的更新,看看这是否有意义?
  • 是的!我想这就是我一直在寻找的东西。基本上,我如何键入参数作为我扩展的相同的改进协议。这样在混合它们时它就不会打我。
猜你喜欢
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多