Swift протокол со связанным типом и стиранием теневого типа - PullRequest
1 голос
/ 01 апреля 2019

Мне нужно передать объект, который реализует протокол со связанным типом в метод, который принимает протокол.Это невозможно в Swift (до последней версии Swift 5), поэтому я использую стирание типов с теневым протоколом на основе этого блога .

protocol ShadowA {
    func test(data: Any) -> String
}

extension ShadowA {
    func test(data: Any) -> String {
        return "shadow"
    }
}

protocol A: ShadowA {
    associatedtype AT

    func test(data: AT) -> String
}

class SpecificA: A {
    typealias AT = Int

    func test(data: Int) -> String {
        return "specific"
    }
}

Проблема в том, что когда я передаюобъект в метод, затем вызывается «реализация по умолчанию тени» вместо «общей».Вы можете проверить игровую площадку , чтобы увидеть, что происходит.

Что-то не так или этот вариант использования вообще невозможен в Swift?

1 Ответ

0 голосов
/ 01 апреля 2019

Эта динамическая отправка и прямая отправка Magic для более подробного объяснения о том, что проверяют эту swift-method-dispatch

Динамическая отправка - это процесс выбора того, какая реализация полиморфная операция (метод или функция) для вызова во время выполнения.

Любой метод, который реализован в protocol extension, является Прямая отправка

я объясню больше

потому что ShadowA равен protocol и имеет default implementation в расширении, поэтому в уме компилятора есть подсказка "Any class can adopt to this protocol without implement this method because it have default implementation"

Прямая отправка

Так что в этой строке Что компилятору известно о test(data:Any) из элемента, и потому что элемент является протоколом с реализацией по умолчанию, поэтому он указывает ему вызвать прямую реализацию по умолчанию

return "in method: \(item.test(data: 0))"

func passedIntoMethod(item: ShadowA) -> String {
    return "in method: \(item.test(data: 0))"
}

Также на этой линии

let a2: ShadowA = SpecificA()   // becuse compiler know only about a2 at this line that it is Protocol so it direct dispatch it  
print(a2.test(data: 0))

Динамическая отправка

Здесь компилятор знает, что a1 является конкретным типом, поэтому он вызывает тестовый метод, который реализован внутри него. если не реализовано, то вызовет реализацию по умолчанию

let a1 = SpecificA()
print(a1.test(data: 0))
...