Использование делегатов в общем протоколе - PullRequest
0 голосов
/ 28 апреля 2018

У меня есть этот код:

protocol GenericProtocol: class {
    associatedtype type
    func funca(component: type)
}

class MyType<T> {

    weak var delegate: GenericProtocol? // First error

    var t: T

    init(t: T) {
        self.t = t
    }

    func finished() {
        delegate?.funca(component: t) // Second error
    }

}

class UsingGenericProtocol: GenericProtocol {

    let myType: MyType<Int>
    typealias type = Int

    init() {
        myType = MyType<Int>(t: 0)
    }

    func funca(component: Int) {

    }

}

Я хочу использовать делегатов с заданным типом. Код не скомпилируется, потому что я получил следующие ошибки:

Протокол 'GenericProtocol' может использоваться только в качестве общего ограничения. потому что он имеет Self или связанные требования типа

И

Элемент 'funca' нельзя использовать для значения типа протокола 'GenericProtocol'; используйте вместо этого общее ограничение

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

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

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

Однако есть несколько обходных путей:

1) Используйте тип делегата в качестве универсального типа:

class MyType<Delegate: GenericProtocol> {
    typealias T = Delegate.type
    ...
}

2) Используйте общий протокол в методе делегата вместо связанного типа:

protocol CommonProtocol { ... }

protocol DelegateProtocol {
    func funca(component: CommonProtocol)
}

3) Используйте замыкания для стирания типов (это также делается в стандартной библиотеке Swift для протокола Sequence с AnySequence<Element>)

struct AnyGenericProtocol<GenericType>: GenericProtocol {
    typealias type = GenericType
    private let f: (GenericType) -> ()

    init<G: GenericProtocol>(_ g: GenericProtocol) where G.type == GenericType {
        f = { component in
            g.funca(component: component)
        }
    }

    func funca(component: GenericType) {
        f(component)
    }
}

class MyType<T> {
    var delegate: AnyGenericProtocol<T>
    ...
}
0 голосов
/ 28 апреля 2018

Невозможно использовать общие протоколы. Вместо этого используйте конкретный тип или обычный протокол. Вы должны объявить конкретный T вне этих абстракций

Например, это должно работать:

class MyType<T> {

    weak var delegate: UsingGenericProtocol<T>? // First error

    var t: T

    init(t: T) {
        self.t = t
    }

    func finished() {
        delegate?.funca(component: t) // Second error
    }

}
class UsingGenericProtocol<T>: GenericProtocol {
    let myType: MyType<T>
    typealias type = T

    init(t: T) {
        myType = MyType<T>(t: t)
    }

    func funca(component: T) {

    }
}

let instance = UsingGenericProtocol<Int>(t: 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...