使用Swift函数,该函数采用通用序列

时间:2018-07-30 03:41:52

标签: swift generics

我现在开始迅速学习,泛型与我以前使用的完全不同。做这样的事情的正确方法是什么?

func createThing<T, Seq: Sequence>(_ type: T.Type, _ block : @escaping (_ sequence: Seq) -> Void) where Seq.Element == T {
    // ...
}

enum MyEnum {
    case A
    case B
}

// error: generic parameter 'Seq' could not be inferred
createThing(MyEnum.Type, { sequence in

    for i in sequence{
        //...
    }
})

我很想直接向createThing<MyEnum>(...)提供一个泛型类型参数,但这显然不是Swift可以做的,并且泛型在协议上的工作方式与它们在其他方面的工作方式大不相同。

1 个答案:

答案 0 :(得分:0)

SeqcreateThing函数的泛型签名的一部分,这意味着编译器需要能够从调用上下文中推断出这个含义,或者明确地告知编译器的具体实现方式Sequence应该可以期待。同样,将Sequence泛型置于功能级别确实会限制您在该功能内可以执行的操作,因为它无法实例化协议。

您可以将(Seq) -> Void块转换为(T) -> Void,并在doSomething中移动序列迭代,这将消除编译错误。在使用时,您可以为type参数添加默认值,这将启用类型推断并自动填充该参数

func createThing<T>(_ type: T.Type = T.self, _ block: (T) -> Void) {
    // ...
    // assuming sequence is create above
    sequence.forEach(block)
}

enum MyEnum {
    case a
    case b
}

// a dedicated function for processing items also means better structured code :) 
func processEnum(_ value: MyEnum) {
    // do your stuff
}

// you can now pass only the second argument
createThing(processEnum)