通用 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)))
}
}
对于所有这些协议混乱,我们深表歉意。为了代码的完整性,我提供了它。问题实际上是关于底部的最后一段代码。
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)))
}
}