Swift: 不能使用 nested/chained 通用类型约束(策略模式)

Swift: Can't use nested/chained generic type constraints (Policy pattern)

我正在 Swift 中实现随机树数据结构。为了限制树的宽度和深度,我决定使用 策略(策略)模式

我的政策是这样的:

protocol BaseTreeNodePolicy {
    static var maximumDepth: Int { get }
    static var maximumWidth: Int { get }
}

我有一个基础 class,看起来像这样:

class BaseTreeNode<PolicyType: BaseTreeNodePolicy> { /* ... */ }

它的一些子class:

class ValueNode<ValueType, PolicyType: BaseTreeNodePolicy>: BaseTreeNode<PolicyType> { /* ... */ }
class ActionNode<PolicyType: BaseTreeNodePolicy>: BaseTreeNode<PolicyType> { /* ... */ }

一切正常,直到我添加这个 class:

final class SequenceNode<ChildType: ActionNode<PolicyType>, PolicyType: BaseTreeNodePolicy>: ActionNode<PolicyType> {
    public var sequence: [ChildType] = []
    // ...
    public override func addRandomDescendants(generator: EntropyGenerator, maxDepth: Int) {
        // ...
        sequence.reserveCapacity(42)
        // ...
        let descendant = ChildType(generator: generator, maxDepth: maxDepth - 1)
        // ...
    }
}

编译 SequenceNode 时,我在这一行遇到编译器错误:

// 'ChildType' is not a subtype of 'ActionNode<PolicyType>'
sequence.reserveCapacity(42)

这一行:

// Type 'PolicyType' does not conform to protocol 'BaseTreeNodePolicy'
let descendant = ChildType(generator: generator, maxDepth: maxDepth - 1)

我不知道有什么问题,因为我在声明的 header 部分清楚地说明了 ChildType: ActionNode<PolicyType>PolicyType: BaseTreeNodePolicy 的类型要求。

有什么问题吗?

提前致谢! 彼得

编辑:重做以实现您的意图:

ActionNode<PolicyType> 不属于参数列表。您仅在 PolicyType:

上进行参数化
final class SequenceNode<PolicyType: BaseTreeNodePolicy> {
    typealias ChildType = ActionNode<PolicyType>
    var sequence = [ChildType]()
    func addRandomDescendants(generator: EntropyGenerator, maxDepth: Int) {
        sequence.reserveCapacity(42)
    }
}

编辑 2:现在您想要更通用。好的,但是您无法将类型依赖项 WITHIN 链接到泛型类型约束列表中。类型约束必须是可直接解析的。这应该使错误清楚:

class _ERROR_SequenceNode<PolicyType, ChildType where PolicyType: BaseTreeNodePolicy, ChildType: ActionNode<PolicyType>> { }

Superclass constraint 'ActionNode' cannot depend on a type parameter

但是,您 ALSO 不能使用 BaseTreeNodePolicy 代替 PolicyType,因为它不具体:

Using 'BaseTreeNodePolicy' as a concrete type conforming to protocol 'BaseTreeNodePolicy' is not supported

因此,由于 ChildType 已经受到泛型类型的约束,该泛型类型必须 可直接实例化 ,因此它本身只能受到已知类型的约束, 外, 具体 实现 BaseTreeNodePolicy.

大图

但是,我认为您正在纠结于泛型,同时错过了简单地完成工作的想法。当您完全控制类型系统的那个分支并且*您不需要return 时,通过泛型进行参数化没有任何价值 ACTUAL 来自函数的通用类型*。

换句话说,我必须在 FooKeyType 上构建一个散列 table,其中 FooKeyType: Hashable 一般参数化,因为我的 class 的用户理所当然地期望 return来自 getKey() 函数的值是 他们的 代码中的实际类型,而不是 Hashable 类型。在这里,您永远不会 return policy 对象,或者即使您这样做了,您也不应该关心它的 return 类型固定为 BaseTreeNodePolicy 而不是一些具体、具体的政策类型。

您可以通过将存储的 属性 抽象类型约束为必要的协议来简单地进行约束。

考虑:

protocol BaseTreeNodePolicy {
    var maximumDepth: Int { get }
    var maximumWidth: Int { get }
}

class BaseTreeNode {
    var policy: BaseTreeNodePolicy

    required init(policy: BaseTreeNodePolicy) {
        self.policy = policy
    }

    // Use 'policy' anywhere now. You've defined a protocol, don't generically parameterize
}

class ValueNode: BaseTreeNode {
    required init(policy: BaseTreeNodePolicy) {
        super.init(policy: policy)
    }
}

class ActionNode: BaseTreeNode {
    required init(policy: BaseTreeNodePolicy) {
        super.init(policy: policy)
    }
}

class SequenceNode<ChildType: ActionNode>: BaseTreeNode {
    var sequence: [ChildType] = []

    required init(policy: BaseTreeNodePolicy) {
        super.init(policy: policy)
    }

    func addRandomDescendants() {
        let c = ChildType(policy: policy)
        sequence.reserveCapacity(42)
    }
}

class FooNode: ActionNode {}

class MyPolicy: BaseTreeNodePolicy {
    var maximumDepth = 3
    var maximumWidth = 5
}

let s = SequenceNode<FooNode>(policy: MyPolicy())