Swift在类型推断和调度优化方面做了大量工作,但是我一直在努力寻找解决方法。我不确定这是Swift的当前限制还是应该作为Radar归档(知道编译器错误很少)。
很抱歉,很长的代码段,例如,这是截短的代码(发布后有更多内容)...
/// Command executor for HTTP transports
class HttpExecutor: Executor {
func execute<T: Command>(command: T) {
print("Not a valid HttpCommand")
}
func execute<T: HttpCommand>(command: T) {
print("HttpCommand")
}
}
/// Simple function, using generic to allow the compiler to infer the same types
/// as those inferred in the constant declarations below.
func performWithExecutor<E: Executor, C: Command>(_ executor: E, command: C) {
executor.execute(command: cmd)
}
// Create command and executor
let cmd = MyCommand()
let httpExecutor = HttpExecutor()
// 1.
// Will output "HttpCommand" (expected)
httpExecutor.execute(command: cmd)
// 2.
// Will output "Not a valid HttpCommand" (unexpected)
performWithExecutor(httpExecutor, command: cmd)
// 3.
let executor: Executor = httpExecutor
// Will output "Not a valid HttpCommand" (expected, not desirable)
executor.execute(command: cmd)
在上面,1
正常工作。代码流可以正确地推断类型,并且可以正确地分派到execute
中的HttpExecutor
的通用变体。
2
是出乎意料的,因为使用泛型函数应该能够传递与内联版本相同的类型信息。
最后,3
有所期望,尽管不理想。
这里有关于工作环境的想法吗?我给了类型擦除一个想法,但似乎会产生相同的结果。
这是其余的代码...
import Foundation
// MARK: - Command
/// Basic of all Sonos API commands
public protocol Command {
associatedtype Request: Encodable
associatedtype Response: Decodable
var name: String { get }
var message: Self.Request? { get }
}
/// A HTTP version of a command
public protocol HttpCommand: Command {
var httpMethod: String { get }
}
// MARK: - Executor
/// Command executor
protocol Executor {
func execute<T: Command>(command: T)
}
//
// MARK: -
//
/// Command to return the groups of a Sonos household
public struct MyCommand: HttpCommand {
public struct Request: Encodable { }
public struct Response: Decodable {
public var items: [String]
}
public init() { }
public var name: String = "items"
public var message: Request?
public var httpMethod: String { "GET" }
}