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

时间:2022-03-18 16:10:11

In the following code, I have a generic protocol Var and it have a private implementation class LambdaVar. Now I want to have a function that return an instance of the LambdaVar without expose it publicly.

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

But I can't find a way to define a function that return a generic protocol type.

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

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?
}

Error:

错误:

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 个解决方案

#1


2  

You should create simple wrapper type of Var like SequenceOf<T>:

您应该创建类似Var的简单包装类型SequenceOf :

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

#1


2  

You should create simple wrapper type of Var like SequenceOf<T>:

您应该创建类似Var的简单包装类型SequenceOf :

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