Swift 通用类型推断
Swift Generic Type Inference
所以我想知道是否有人可以解释这个错误背后的原因或我做错了什么的解释。
我正在尝试创建一个通用函数,该函数采用协议约束类型,该类型上有一个名为 solve 的静态方法。
但出于某种原因,即使它很好地解决了 Xcode 中的约束,编译器也会发出嘶嘶声。
有什么原因它不能推断出我已经指定的类型,或者我的代码示例中是否存在天真的错误?
编辑:因为它不够明确
我知道如何解决它,我只是想知道为什么接口/协议中的静态成员有问题的解释。
protocol NodeSolver {
static func solve(_ nodes: [Node]) -> [Node]
}
func findPath<T: NodeSolver>(nodes: [Node]) -> [Node] {
return T.solve(nodes)
}
因为您似乎希望 findPath
成为与符合 NodeSolver
的 类型 紧密相关的方法,但不会使用此方法的任何实例findPath
方法本身中的具体 NodeSolver
类型,您可能需要考虑简单地将通用 findPath
方法添加为默认实现可用于所有符合 [=14= 的类型的类型方法].
例如:
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)
I am handing a constrained type in the protocol I am specifying. And
the actual type in the method call.
findPath<NodeSolver1>(nodes)
findPath<NodeSolver2>(nodes)
另一种可能更接近您要实现的解决方法是将泛型函数包装到一个泛型类型(例如,struct
)中,它包含一个非泛型函数 findPath
w.r.t。通用类型的具体版本。如果从拥有类型之外的角度查看包装的 findPath
,则函数是通用的 w.r.t。拥有类型的通用类型持有者。
例如:
struct Node {}
protocol NodeSolver {
static func solve(_ nodes: [Node]) -> [Node]
}
struct NodeSolverA: NodeSolver {
static func solve(_ nodes: [Node]) -> [Node] {
return nodes
}
}
struct NodeSolverB: NodeSolver {
static func solve(_ nodes: [Node]) -> [Node] {
return nodes.reversed()
}
}
// instead of a generic function, wrap a concrete function
// in a generic type
struct AnyNodeSolver<T: NodeSolver> {
static func findPath(nodes: [Node]) -> [Node] {
return T.solve(nodes)
}
}
let myNodes = [Node(), Node()]
let dummyPathA = AnyNodeSolver<NodeSolverA>.findPath(nodes: myNodes)
let dummyPathB = AnyNodeSolver<NodeSolverB>.findPath(nodes: myNodes)
您必须在函数签名中指定 T
的类型。
func findPath<T: NodeSolver>(nodes: [Node], ofType type: T.Type) -> [Node] {
return T.solve(nodes)
}
如果您定义了泛型类型,您必须使编译器能够以某种方式推断出实际类型。目前没有办法实现这一目标。您将如何使用不同的 NodeSolver
s 对该方法进行两次调用?
Yannick 写了一个指定类型的答案 - 你问 "Then what is the point of the generic? If you have to specify it twice?" - 你不必这样做。一般示例:
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)
}
所以我想知道是否有人可以解释这个错误背后的原因或我做错了什么的解释。
我正在尝试创建一个通用函数,该函数采用协议约束类型,该类型上有一个名为 solve 的静态方法。
但出于某种原因,即使它很好地解决了 Xcode 中的约束,编译器也会发出嘶嘶声。
有什么原因它不能推断出我已经指定的类型,或者我的代码示例中是否存在天真的错误?
编辑:因为它不够明确
我知道如何解决它,我只是想知道为什么接口/协议中的静态成员有问题的解释。
protocol NodeSolver {
static func solve(_ nodes: [Node]) -> [Node]
}
func findPath<T: NodeSolver>(nodes: [Node]) -> [Node] {
return T.solve(nodes)
}
因为您似乎希望 findPath
成为与符合 NodeSolver
的 类型 紧密相关的方法,但不会使用此方法的任何实例findPath
方法本身中的具体 NodeSolver
类型,您可能需要考虑简单地将通用 findPath
方法添加为默认实现可用于所有符合 [=14= 的类型的类型方法].
例如:
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)
I am handing a constrained type in the protocol I am specifying. And the actual type in the method call.
findPath<NodeSolver1>(nodes) findPath<NodeSolver2>(nodes)
另一种可能更接近您要实现的解决方法是将泛型函数包装到一个泛型类型(例如,struct
)中,它包含一个非泛型函数 findPath
w.r.t。通用类型的具体版本。如果从拥有类型之外的角度查看包装的 findPath
,则函数是通用的 w.r.t。拥有类型的通用类型持有者。
例如:
struct Node {}
protocol NodeSolver {
static func solve(_ nodes: [Node]) -> [Node]
}
struct NodeSolverA: NodeSolver {
static func solve(_ nodes: [Node]) -> [Node] {
return nodes
}
}
struct NodeSolverB: NodeSolver {
static func solve(_ nodes: [Node]) -> [Node] {
return nodes.reversed()
}
}
// instead of a generic function, wrap a concrete function
// in a generic type
struct AnyNodeSolver<T: NodeSolver> {
static func findPath(nodes: [Node]) -> [Node] {
return T.solve(nodes)
}
}
let myNodes = [Node(), Node()]
let dummyPathA = AnyNodeSolver<NodeSolverA>.findPath(nodes: myNodes)
let dummyPathB = AnyNodeSolver<NodeSolverB>.findPath(nodes: myNodes)
您必须在函数签名中指定 T
的类型。
func findPath<T: NodeSolver>(nodes: [Node], ofType type: T.Type) -> [Node] {
return T.solve(nodes)
}
如果您定义了泛型类型,您必须使编译器能够以某种方式推断出实际类型。目前没有办法实现这一目标。您将如何使用不同的 NodeSolver
s 对该方法进行两次调用?
Yannick 写了一个指定类型的答案 - 你问 "Then what is the point of the generic? If you have to specify it twice?" - 你不必这样做。一般示例:
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)
}