Swift 5 Dynami c отправка не маршрутизации, как ожидалось - PullRequest
0 голосов
/ 10 января 2020

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 работает, как ожидалось. Поток кода может правильно выводить типы и может правильно отправлять вариант c generic execute в HttpExecutor.

2 неожиданно, поскольку использование функции generi c должно быть способен переносить ту же информацию о типе, что и встроенная версия.

Наконец, 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" }
}
...