Что эквивалентно C # или универсальному интерфейсу Java в Swift? - PullRequest
1 голос
/ 28 марта 2019

Я новичок Свифта из C #. Я начал проектировать программу Swift с абстрактного уровня - объявлять подписи сущностей с отношениями между ними. Я поймал, что протокол в swift является аналогом интерфейса в C # или Java. С моей (как новичок в Swift из C #), дженерики в протоколах реализованы в Swift необычным способом. Я исследовал связанные типы, но постоянно не знал, как сделать следующее:

typealias Observer<T> = (T) -> ()

protocol Subscription {
    func cancel()
}

protocol Observable<T> {
    func subscribe(observer: Observer<T>) -> Subscription
}

protocol A {}
protocol B {}
protocol C {}

protocol AbcObservable {
  var aAdded : Observable<A> { get }
  var bAdded : Observable<B> { get }
  var cAdded : Observable<C> { get }
}

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


Примечание 1

Мне нужно, чтобы описанная архитектура обеспечивала что-то вроде следующего:

class First: AbcObservable { ... }
class Second: AbcObservable { ... }

class Client {
  let lightDependency: AbcObservable
  init(lightDependency: AbcObservable) {
    self.lightDependency = lightDependency
  }
}

class IoCContainer1 {
  let client: Client
  init() {
    let abc: AbcObservable = First()
    client = Client(abc)
  }
}

class IoCContainer2 {
  let client: Client
  init() {
    let abc: AbcObservable = Second()
    client = Client(abc)
  }
}

class Mock: AbcObservable { ... }

class Test {
  func test() {
    let abcMock = Mock()
    let client = Client(abcMock)
    ...
  }
}

Этот момент очень болезнен для меня; Я не могу понять, как я могу предоставить D SOLID в моем коде в случае, когда мне нужны дженерики.


Замечание 2

Observable не будет иметь много реализаций в реальной ситуации, и глупо делать это как абстрактное. Я хотел написать суть моей проблемы, и я использовал Observable в примере, чтобы упростить. В реальной ситуации у меня был DataManager вместо Observable, который имеет много реализаций.


Примечание 3

Вопрос был изменен с "Как использовать протокол с ассоциированным типом в другом протоколе?" «Что эквивалентно для универсального интерфейса C # или Java в Swift?»

1 Ответ

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

Вы использовали здесь слишком много протоколов, но вам нужен именно такой синтаксис.Некоторые из этих частей не могут быть разумно протоколами.У меня проблемы с представлением трех различных реализаций Observable, и, конечно, не подписки.(Если вы не можете представить три реализации, это, вероятно, не протокол.) Попытка превратить Observable в протокол определенно приводит к взрыву.

Подписка - это просто оболочка вокруг функции, так что это struct,Наблюдаемый, естественно, класс.Остальное возможно хорошо;ваши проблемы в основном имеют синтаксис.

import Foundation

typealias Observer<T> = (T) -> ()

struct Subscription {
    let cancel: () -> Void
}

final class Observable<T> {
    private var observations: [UUID: Observer<T>] = [:]
    func subscribe(observer: @escaping Observer<T>) -> Subscription {
        let uuid = UUID()
        observations[uuid] = observer
        return Subscription(cancel: { [weak self] in self?.observations[uuid] = nil })
    }
}

protocol A {}
protocol B {}
protocol C {}

protocol AbcObservable {
    var aAdded : Observable<A> { get }
    var bAdded : Observable<B> { get }
    var cAdded : Observable<C> { get }
}

struct First: AbcObservable {
    let aAdded = Observable<A>()
    let bAdded = Observable<B>()
    let cAdded = Observable<C>()
}

struct Second: AbcObservable {
    let aAdded = Observable<A>()
    let bAdded = Observable<B>()
    let cAdded = Observable<C>()
}

struct Client {
    let lightDependency: AbcObservable
    init(lightDependency: AbcObservable) {
        self.lightDependency = lightDependency
    }
}

struct IoCContainer1 {
    let client: Client
    init() {
        let abc: AbcObservable = First()
        client = Client(lightDependency: abc)
    }
}

class IoCContainer2 {
    let client: Client
    init() {
        let abc: AbcObservable = Second()
        client = Client(lightDependency: abc)
    }
}

struct Mock: AbcObservable {
    let aAdded = Observable<A>()
    let bAdded = Observable<B>()
    let cAdded = Observable<C>()
}

class Test {
    func test() {
        let abcMock = Mock()
        let client = Client(lightDependency: abcMock)
    }
}

Реализация Observer здесь основана на моей Subject реализации.Обратите внимание, что это часть системы, в которой есть несколько причуд, которые мне не нравятся (Syzygy Дэйва Делонга лучше).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...