gpt4 book ai didi

swift - 有什么方法可以确定子协议(protocol)的一致性,例如是否符合 Swift 2 中的通用协议(protocol)(在运行时或编译期间)?

转载 作者:行者123 更新时间:2023-11-28 09:27:39 24 4
gpt4 key购买 nike

我正在将 Java 库移植到 Swift 2.0,但在使用泛型方面遇到了一些麻烦。

我有以下协议(protocol)层次结构:

public protocol Graph {
typealias V: Hashable
typealias E: Hashable

func getAllEdges(sourceVertex: V, targetVertex: V) -> Set<E>?
func getEdge(sourceVertex: V, targetVertex: V) -> E?
func getEdgeFactory() -> EdgeFactory<V, E>?
func addEdge(sourceVertex: V, targetVertex: V) -> E?
func addEdge(sourceVertex: V, targetVertex: V, e: E) -> Bool
func addVertex(v: V) -> Bool
func containsEdge(sourceVertex: V, targetVertex: V) -> Bool
func containsEdge(e: E) -> Bool
func containsVertex(v: V) -> Bool
func edgeSet() -> Set<E>
func edgesOf(v: V) -> Set<E>
func removeAllEdges<T: CollectionType where T.Generator.Element == E>(edges: T) -> Bool
func removeAllEdges(sourceVertex: V, targetVertex: V) -> Set<E>?
func removeAllVertices<T: CollectionType where T.Generator.Element == V>(vertices: T) -> Bool
func removeEdge(sourceVertex: V, targetVertex: V)
func removeEdge(e: E) -> Bool
func removeVertex(v: V) -> Bool
func vertexSet() -> Set<V>
func getEdgeSource(e: E) -> V
func getEdgeTarget(e: E) -> V
func getEdgeWeight(e: E) -> Double
}

public protocol DirectedGraph: Graph {
func inDegreeOf(vertex: V) -> Int
func incomingEdgesOf(vertex: V) -> Set<E>
func outDegreeOf(vertex: V) -> Int
func outgoingEdgesOf(vertex: V) -> Set<E>
}

public protocol UndirectedGraph: Graph {
func degreeOf(vertex: V) -> Int
}

下面是引起麻烦的类的定义:

public class CrossComponentIterator
<V: Hashable, E: Hashable, D, G: Graph
where G.V == V, G.E == E>
: AbstractGraphIterator<V, E>

也就是说,它有一种方法,该方法应该根据传递的图的实际类型(DirectedGraph 或 UndirectedGraph)初始化其变量之一。

我已经尝试通过声明多个版本的函数来解决这个问题:

func createGraphSpecifics<DG: Graph where DG: DirectedGraph, DG.V == V, DG.E == E>(graph: DG)
-> CrossComponentIteratorSpecifics<V, E>
{
return DirectedSpecifics<V, E, DG>(graph: graph)
}

func createGraphSpecifics<UG: Graph where UG: UndirectedGraph, UG.V == V, UG.E == E>(graph: UG)
-> CrossComponentIteratorSpecifics<V, E>
{
return UndirectedSpecifics<V, E, UG>(graph: graph)
}

func createGraphSpecifics<GG: Graph where GG.V == V, GG.E == E>(graph: GG)
-> CrossComponentIteratorSpecifics<V, E>
{
fatalError("Unknown graph type instance")
}

但不幸的是,对于图的任何实例(即使它符合“DirectedGraph”或“UndirectedGraph”)只调用最新版本的函数

而且我知道,也许我可以通过将协议(protocol) DirectedGraph 和 UndirectedGraph 转换为抽象类来解决这个问题(我指的是在每个声明的函数中都有 fatalError() 的类,因为 Swift 在法律上不支持抽象类)。

但也许还有另一种更优雅、更 Swifty 的解决方案?

在 Java 中这是微不足道的——在运行时检查接口(interface)的一致性:

if (g instanceof DirectedGraph<?, ?>) {
return new DirectedSpecifics<V, E>((DirectedGraph<V, E>) g);
} else {
return new UndirectedSpecifics<V, E>(g);
}

编辑这是我想要实现的最少代码:

protocol P {
// This typealias makes impossible to use 'P'
// (or its descendants) as a type.
// It can be used only as generic constraint.
typealias A

// myfunc is needed for compiler to infer 'A'
func myfunc(a: A)
}
protocol P1:P {
func p1specific(a: A)
}
protocol P2:P {
func p2specific(a: A)
}

struct S<T:P> {
init(t: T) {
// TODO: check if 't' conforms to 'P1', 'P2', both or neither
}
}

// Examples of concrete implementations of 'P1' and 'P2'
struct S1<X>:P1{
func myfunc(a: X) {}
func p1specific(a: X) {}
}
struct S2<X>:P2{
func myfunc(a: X) {}
func p2specific(a: X) {}
}

最佳答案

Is there any way to determine sub-protocol conformance for instance conforming to generic protocol in Swift 2 (at runtime or during compilation)?

是的。

这是我实现类型删除的技巧,因此可以利用运行时。观察 _P:

protocol _P {
static var _A: Any.Type { get }
func _myfunc(_a: Any) -> Void?
}

extension _P where Self: P {

static var _A: Any.Type {
return A.self
}

func _myfunc(_a: Any) -> Void? {
return (_a as? A).map(myfunc)
}
}

protocol P {
typealias A

func myfunc(a: A)
}

protocol _P1:_P {
func _p1specific(_a: Any) -> Void?
}

extension _P1 where Self: P1 {
func _p1specific(_a: Any) -> Void? {
return (_a as? A).map(p1specific)
}
}

protocol P1:_P1, P {
func p1specific(a: A)
}

protocol _P2:_P {
func _p2specific(_a: Any) -> Void?
}

extension _P2 where Self: P2 {
func _p2specific(_a: Any) -> Void? {
return (_a as? A).map(p2specific)
}
}

protocol P2:_P2, P {
func p2specific(a: A)
}

您现在可以确定一个值是否符合 P1P2,并相应地强制转换。此外,通用参数 A 现在可通过不透明的 Any.Type 使用。

(x as?_P1) != nil ?真:假

关于swift - 有什么方法可以确定子协议(protocol)的一致性,例如是否符合 Swift 2 中的通用协议(protocol)(在运行时或编译期间)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33843876/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com