泛型类如何使带有约束的协议带有init的协议相符?

问题描述

抱歉,所有这些协议混乱。我出于代码完整性的目的提供它。问题实际上是关于底部的最后一块代码

protocol Edgedable: Hashable {
    associatedtype Edge: Destinationable
    var edges: Set<Edge> { get set }
}

protocol Destinationable: Hashable {
    associatedtype D: Hashable
    var destination: D { get set }
}

class Graph<Node: Edgedable>: ExpressibleByDictionaryLiteral {
    typealias Edge = Node.Edge
    typealias D = Edge.D
    private var storage: [D: Node]
    
    init(_ tuples: [(D,Node)]) {
        self.storage = .init(uniqueKeysWithValues: tuples)
        // Some Postinit code here
    }

    required convenience init(dictionaryLiteral elements: (D,Node)...) {
        self.init(elements)
    }
}

extension Graph: ExpressibleByArrayLiteral where D == Int {
    
    required convenience init(arrayLiteral elements: Node...) {
        self.init(Array(zip(0...,elements)))
    }
}

在这里选择一种标准方法:通过扩展。看起来正是我所需要的。也就是说,该类仅在D == Int的情况下实现协议 但是代码无法编译:

'required'初始化程序必须在类中直接声明 “图形”(不在扩展名中)

初始化器要求'init(arrayLiteral :)'仅可通过满足 非最终类定义中的“必需”初始化程序 “图”

Okey,我可以直接在类中声明它,就像我对另一个init(和另一个对应的协议)所做的一样。但是如何设置约束!?

class Graph<Node: Edgedable>: ExpressibleByDictionaryLiteral,ExpressibleByArrayLiteral where Node.Edge.D == Int {

这是不正确的。该声明具有不同的含义。不是我要实现的目标。

解决方法

我不知道有没有制作图表final的方法。但是,如果您将其设为final,则只要删除requiredrequired对于没有子类的东西就没有任何意义),它就可以正常工作:

extension Graph: ExpressibleByArrayLiteral where D == Int {
    convenience init(arrayLiteral elements: Node...) {
        self.init(Array(zip(0...,elements)))
    }
}