2016-03-08 133 views
2

我认为我对Swift类型/协议/泛型的认知已经溢出。我一直在使用扩展“的输入流的字节”的模式做一样的东西: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类型的灯泡闪烁。有些日子我真的很喜欢这门语言。其他时候,我觉得我正在大吼大叫我的狗试图让他来,他只是盯着我不动,然后转身追逐街道。

+0

“没有一个IndexingGenerator符合GeneratorType” 是的但不是每个GeneratorType是IndexingGenerator。 – matt

+0

我只是因为我无法弄清楚如何更通用地做这个参数,所以'IndexingGenerator <[UInt8]>'的参数。我真的不关心它是一个IndexingGenerator。只要产生UInt8,我就可以使用任何类型的Generator。有没有办法让一个参数是一个适当规格的协议? –

+0

诀窍是要声明符合'GeneratorType'的* new *协议,并以某种方式限制符合类型具有'UInt8'的元素? –

回答

2

试试这个:

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)) 
    } 
} 
+0

可以说'guard var vSelf'并缩短一行:) – matt

+0

@matt LOL。老实说,我从来不会在'guard'中使用'var',我认为我做不到!我是多么愚蠢......谢谢你的提示。 –

+0

这迫使我把可选的返回类型封装起来。不是世界末日,但不是我想要的。我试图弥合不得不使用协议来扩展泛型,但必须传递泛型作为参数的类型之间的差距。 –