如何创建一个返回通用协议类型的函数?

时间:2014-10-21 10:29:24

标签: swift

在以下代码中,我有一个通用协议Var,它有一个私有实现类LambdaVar。现在我希望有一个函数返回LambdaVar的实例而不公开它。

但是我无法找到一种方法来定义返回通用协议类型的函数。

public protocol Var {
    typealias ValueType
    var value : ValueType { get }
}

struct LambdaVar<T> : Var {
    let _get : Void -> T
    init(_ f : Void -> T)
    {
        _get = f
    }
    var value : T {
        get {
            return _get()
        }
    }
}

public func transform<T : Var, U>(v : T, f : T.ValueType -> U) -> Var<U> {
    return LambdaVar<U>() { f(v.value) }                       // ^^^^^^ what to put here?
}

错误:

Playground execution failed: <EXPR>:26:67: error: cannot specialize non-generic type 'Var'
public func transform<T : Var, U>(v : T, f : T.ValueType -> U) -> Var<U> {
                                                                  ^
<EXPR>:26:67: error: protocol 'Var' can only be used as a generic constraint because it has Self or associated type requirements
public func transform<T : Var, U>(v : T, f : T.ValueType -> U) -> Var<U> {

1 个答案:

答案 0 :(得分:2)

您应该创建Var的简单包装类型,例如SequenceOf<T>

struct VarOf<T>:Var {
    let f:Void->T
    init<V:Var where V.ValueType == T>(_ v:V) {
        f = { v.value }
    }
    var value:T {
        return f()
    }
}

func transform<T : Var, U>(v : T, f : T.ValueType -> U) -> VarOf<U> {
    return VarOf(LambdaVar<U>({ f(v.value) }))
}

let intVar = VarOf(LambdaVar({ 12 }))
let floatVar = transform(intVar, { Float($0) })
floatVar.value // -> 12.0