Как вызвать реализацию расширения протокола по умолчанию с ограничениями типа

Рассмотрим следующий пример:

class ManObj {
    func baseFunc() {
        print("ManObj baseFunc")
    }
}

class SubObj: ManObj {
}

protocol Model {
}

extension Model { // This is protocol extension
    func someFunc() { // Protocol extension default implementation
        (self as! ManObj).baseFunc()
        print("Model implementation")
    }
}
extension SubObj: Model {
    func someFunc() {
        print("SubObj Implementation")
    }
}

let list = SubObj()
list.someFunc() // static dispatching

let list2: Model = SubObj()
list2.someFunc() // dynamic dispatching

Вывод приятный:

SubObj Implementation
ManObj baseFunc
Model implementation

Но мне не нравится кастинг в строке (self as! ManObj).baseFunc().

На самом деле, я планирую применять протокол Model только к подклассам ManObj. (Но не все подклассы ManObj являются Model!) Итак, я попытался изменить Model на:

extension Model where Self: ManObj {
    func someFunc() {
        self.baseFunc() // No more casting needed!
        print("Model implementation")
    }
}

Но меня встречает ошибка:

list2.someFunc() <- error: 'Model' is not a subtype of 'ManObj'

Итак, есть ли способ вызвать Model.someFunc из list2 после того, как я ограничу Model до where Self: ManObj?


person ewcy    schedule 18.03.2017    source источник


Ответы (1)


Создайте пустой класс только для приведения типов

class ManObj {
    func baseFunc() {
        print("ManObj baseFunc")
    }
}

class SubObj: ModelCaster {
    func someFunc() {
        print("SubObj Implementation")
    }
}

protocol Model {
}

extension Model where Self: ModelCaster { // This is protocol extension
    func someFunc() { // Protocol extension default implementation
        print("Model implementation")
    }
}

class ModelCaster: ManObj, Model{

}

let list = SubObj()
list.someFunc() //SubObj Implementation

let list2: ModelCaster = SubObj()
list2.someFunc() //Model implementation
person vk.edward.li    schedule 21.03.2017