通用 class 如何使协议(其中包含 init)符合约束条件?

How a generic class to conform a protocol (that have init in it) with constraint?

对于所有这些协议混乱,我们深表歉意。为了代码的完整性,我提供了它。问题实际上是关于底部的最后一段代码。

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

我在这里选择标准方法:通过扩展。它看起来正是我需要的。即 class 仅在 D == Int 的情况下执行协议 但代码无法编译:

'required' initializer must be declared directly in class 'Graph' (not in an extension)

Initializer requirement 'init(arrayLiteral:)' can only be satisfied by a 'required' initializer in the definition of non-final class 'Graph'

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

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

这是不正确的。该声明具有不同的含义。不是我想要达到的。

我不知道有什么方法可以在不制作图表的情况下实现这一目标 final。但是,如果你确实做到了 final,只要你删除 required 就可以正常工作(如果不能有子类,required 就没有任何意义):

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