简体   繁体   English

通用类如何使协议(其中包含 init)与约束一致?

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

Sorry for all these protocol mess.很抱歉所有这些协议混乱。 I provide it for the sake of code completeness.我提供它是为了代码完整性。 The question is actually about the last chunk of the code at the bottom.问题实际上是关于底部的最后一块代码。

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

I choose a standard approach here: via extension.我在这里选择了一种标准方法:通过扩展。 It looks like exactly what I need.它看起来正是我需要的。 That is the class implements the protocol only in the case of D == Int But the code doesn't compile:即类仅在D == Int的情况下才实现协议,但代码不编译:

'required' initializer must be declared directly in class 'Graph' (not in an extension) “必需”初始化程序必须直接在类“Graph”中声明(不在扩展中)

Initializer requirement 'init(arrayLiteral:)' can only be satisfied by a 'required' initializer in the definition of non-final class 'Graph'初始化器要求 'init(arrayLiteral:)' 只能由非最终类 'Graph' 定义中的“必需”初始化器满足

Okey, I can declare it directly in class, exactly like I did with another init (and another corresponding protocol).好吧,我可以直接在类中声明它,就像我对另一个 init(和另一个相应的协议)所做的一样。 But how to set the constraint!?但是如何设置约束!?

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

This is not correct.这是不正确的。 This declaration has a different meaning.这个声明有不同的含义。 Not that I'm trying to achieve.不是我想要实现。

I don't know of a way to achieve this without making Graph final .我不知道有什么方法可以在不使 Graph final情况下实现这一目标。 If you do make it final , however, it will work fine as long as you remove required ( required doesn't mean anything if there can't be subclasses):但是,如果您确实将其设为final ,则只要您删除required ,它就可以正常工作(如果不能有子类, required并不意味着什么):

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM