Протокол с обобщениями и специализацией - PullRequest
2 голосов
/ 13 марта 2019

Есть ли способ определить универсальную функцию в протоколе и позволить соответствующему объекту определить специализации для этого протокола?Например:

protocol Generic {
    func generic<T>(prop: T, otherProp: String)
}

class Gen: Generic {
    func generic<T>(prop: T, otherProp: String) {
        print("generic")
    }

    func generic(prop: String, otherProp: String) {
        print(prop)
    }
}

Теперь, если я использую класс следующим образом:

let inst = Gen()
inst.generic(prop: 1, otherProp: "Go")
inst.generic(prop: "Hello", otherProp: "Stop")

Я получу ожидаемый результат:

generic
Hello

Однако, если я объявлюinst будет иметь тип Generic:

let inst: Generic = Gen()
inst.generic(prop: 1, otherProp: "Go")
inst.generic(prop: "Hello", otherProp: "Stop")

Я получу:

generic
generic

Итак, если у меня есть свойство типа Generic, я не могу использоватьспециализация обобщенной функции от разработчика протокола.Это ожидаемое поведение?Есть ли способ достичь поведения, которое я ищу, то есть использовать специализацию обобщенной функции, даже если доступ осуществляется через интерфейс протокола?Я был бы признателен за понимание этого.Спасибо всем.

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Если вы объявите требование протокола как универсальную функцию, вы не сможете вызвать более специализированную перегруженную версию этой же функции через тип протокола. Тем не менее, вы можете специализировать реализацию обобщенной функции для вашего принимающего класса, проверив тип универсального входного аргумента.

class Gen: Generic {
    func generic<T>(prop: T, otherProp: String) {
        if prop is String {
            print(prop)
        } else {
            print("generic")
        }
    }
}

let inst: Generic = Gen()
inst.generic(prop: 1, otherProp: "Go")
inst.generic(prop: "Hello", otherProp: "Stop")
0 голосов
/ 14 марта 2019

Вы можете добавить сигнатуру метода generic(String, String) в протокол и добавить реализацию по умолчанию с расширением:

protocol Generic {
    func generic<T>(prop: T, otherProp: String)
    func generic(prop: String, otherProp: String)
}

extension Generic {
    func generic(prop: String, otherProp: String) {
        generic(prop: prop as Any, otherProp: otherProp)
    }
}
...