Swift通用类型推断

时间:2017-02-25 13:12:49

标签: swift generics types protocols inference

所以我想知道是否有人可以解释这个错误背后的理性或解释我做错了什么。

我正在尝试创建一个泛型函数,该函数采用协议约束类型,其上有一个名为solve的静态方法。

但由于某些原因,即使它在Xcode中解决了约束,编译器也会抛出一个怪异的东西。

是否有任何理由它无法推断出我已经指定的类型或我的代码示例中是否存在天真错误?

编辑:因为它不够明确

我知道如何解决这个问题,我只是想解释为什么接口/协议中的静态成员存在问题。

enter image description here

protocol NodeSolver {
    static func solve(_ nodes: [Node]) -> [Node]
}

func findPath<T: NodeSolver>(nodes: [Node]) -> [Node]  {        
        return T.solve(nodes)
    }

4 个答案:

答案 0 :(得分:1)

由于您似乎希望findPath成为与符合NodeSolver类型强关联的方法,但不会使用此具体{{1}的任何实例在NodeSolver方法本身中输入,您可能需要考虑简单地将常规findPath方法添加为默认实现可用于符合findPath的所有类型的类型方法。

E.g:

NodeSolver
  

我在我指定的协议中处理约束类型。和   方法调用中的实际类型。

struct Node {}

protocol NodeSolver {
    static func solve(_ nodes: [Node]) -> [Node]
    static func findPath(nodes: [Node]) -> [Node]
}

extension NodeSolver {
    static func findPath(nodes: [Node]) -> [Node]  {
        // hopefully some more logic ...
        return Self.solve(nodes)
    }
}

struct MyNodeSolver: NodeSolver {
    // dummy solver
    static func solve(_ nodes: [Node]) -> [Node] {
        return nodes
    }
}

let myNodes = [Node(), Node()]

// make use of the default implementation of `findPath` available
// to all types conforming to 'NodeSolver': this method itself
// make use of the concrete type-specific implementation of 'solve'
// in the types conforming to 'NodeSolver'.
let dummyPath = MyNodeSolver.findPath(nodes: myNodes)

另一种解决方法,可能更接近你想要实现的目的,是将泛型函数包装成一个泛型类型(比如findPath<NodeSolver1>(nodes) findPath<NodeSolver2>(nodes) ),它包含一个非泛型函数struct WRT泛型的具体版本。如果从拥有类型外部的视点查看包装的findPath,则函数是通用的w.r.t.拥有类型的通用类型持有者。

E.g:

findPath

答案 1 :(得分:1)

您必须在函数签名中指定const dynamicUrl = query => `www.example.com/${query}/current.json` console.log(dynamicUrl('es6')) //=> 'www.example.com/es6/current.json'的类型。

T

答案 2 :(得分:1)

如果定义泛型类型,则必须使编译器以某种方式推断实际类型。目前没有办法实现这一目标。你如何使用不同的NodeSolver s对该方法进行两次调用?

Yannick写了一个指定类型的答案 - 你问&#34;那么泛型的重点是什么?如果你必须指定它两次?&#34; - 你不必。一般例子:

protocol P {
    static func solve(argument : String)
}

class P1 : P {
    class func solve(argument : String) {
        print("first")
    }
}

class P2 : P {
    class func solve(argument : String) {
        print("second")
    }
}


func doSome(argument : String, a : P.Type) {
    a.solve(argument: argument)
}

doSome(argument: "", a: P1.self) // prints "first"
doSome(argument: "", a: P2.self) // prints "second"

在你的情况下:

func findPath(nodes: [Node], solver: NodeSolver.Type) -> [Node]  {        
    return solver.solve(nodes)
}

答案 3 :(得分:0)

与一位回复此事的同事交谈(它在c#中但与之相关)

并在语言实现方面解释了这个问题的问题。

感谢您的所有答案和时间。

https://blogs.msdn.microsoft.com/ericlippert/2007/06/14/calling-static-methods-on-type-parameters-is-illegal-part-one/