如何解决“协议……只能作为通用约束……" [英] how to solve "Protocol ... can only be used as a generic constraint..."

查看:59
本文介绍了如何解决“协议……只能作为通用约束……"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这段代码:

public protocol Evaluable {
    typealias ReturnType
    func eval(s: State) -> ReturnType
}

protocol AlgebraicExpr : Evaluable {
}

public struct Const : AlgebraicExpr {
    var value: Int = 0

    public func eval(s: State) -> Int {
        return value
    }
}

public struct Add : AlgebraicExpr {
    let a, b: AlgebraicExpr

    public func eval(s: State) -> Int {
        return a.eval() + b.eval()
    }
}

它是无效的,因为 Add 不能有 AlgebraicExpr 变量.

it is invalid because Add cannot have an AlgebraicExpr variable.

但我真的需要 Add 来存储两个 AlgebraicExpr.你会如何在 Swift 中解决这个问题?

But I really need Add to store two AlgebraicExprs. How would you solve this in Swift?

为了完整性,State 只是一个结构体,例如:

For completeness, State is just a struct, for example:

public struct State {
    var env = Dictionary<String, Int>()

    init(_ d: Dictionary<String, Int> = [:]) {
        env = d
    }

    subscript(s: String) -> Int? {
        get {return env[s]}
        set {env[s] = newValue}
    }
}

推荐答案

你不能存储两个依赖于 Self 的协议,或者一个 typealias 因为当抽象为协议,功能未定.如果不了解 ReturnType 的值,类型 Evaluable 没有实际意义,因此系统不可能逻辑地运行并了解应该返回什么.

You can't store two protocols that rely on Self, or a typealias because when abstracted as a protocol, the functionality is undetermined. Type Evaluable has no real meaning without understanding the value of ReturnType, so it's not possible for the system to function logically and understand what should be returned.

以这样的事情为例(无效)

Take for instance something like this (not valid)

let thing: Evaluable = ...
let result = thing.eval(state) // What should return type be?

不能单独通过协议推断返回类型,它需要指定类型的实现,通过定义typealias ReturnType

The return type can't be inferred through the protocol alone, it requires an implementation by a specified type that gives more knowledge about its behavior by defining the typealias ReturnType

这些可以作为泛型约束的原因是可以通过泛型参数推断实现.

The reason these can function as generic constraints is that the implementation can be inferred through the generic parameters.

func genericConstrained<T: Evaluable>(evaluable: T, state: State) -> T.ReturnType {
    return evaluable.eval(state)
}

在此示例中,当我们对特定的符合条件的对象调用 genericConstrained 时,可以推断出它的所有其他功能.

In this example, when we call genericConstrained on a particular conforming object, all of its other functionality can be inferred.

tl;dr

但是,如果您还限制了您的包,您可以随心所欲:

If however, you also constrain your package, you could do as you wish:

public struct Add<ExpressionType : AlgebraicExpr> : AlgebraicExpr {
    let a, b: ExpressionType

    public func eval(s: State) -> ExpressionType.ReturnType {
        return a.eval() + b.eval()
    }
}

然后使用like

let add: Add<SomeConformingType> = ...

这篇关于如何解决“协议……只能作为通用约束……"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆