Быстрый. Внутренний тип в публичном протоколе

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

Итак, у меня есть этот протокол и тип, который я хочу иметь внутренним:

internal protocol ATCoreInstrumentProtocol { // SOME STUFF }
internal typealias AT_1G_WaveInstrumentType = //Somethings that conforms to ATCoreInstrumentProtocol

Затем у меня есть этот InstrumentType, который я хочу сделать общедоступным. Проблема здесь в том, что ASSOCIATED_INSTRUMENT aka ATCoreInstrumentProtocol должен быть internal, и поэтому я не могу использовать его таким образом. Нет возможности сделать ATCoreInstrumentProtocol общедоступным.

public protocol InstrumentType {
  static var instrumentType: SupportedInstrumentTypes { get }
  associatedtype ASSOCIATED_INSTRUMENT: ATCoreInstrumentProtocol
}

public final class InstrumentTypes {
  private init() {}

  public final class AT_1G_Wave : InstrumentType {
      public class var instrumentType: SupportedInstrumentTypes { get { return .wave_1G } }
      public typealias ASSOCIATED_INSTRUMENT = AT_1G_WaveInstrumentType
  }
}

Вот как я хочу его использовать.

internal class ATCoreInteractor<IT: InstrumentType> {

  internal var instrumentObservable : Observable<IT.ASSOCIATED_INSTRUMENT> {
      return self.instrumentSubject.asObservable()
  }

  private var instrumentSubject = ReplaySubject<IT.ASSOCIATED_INSTRUMENT>.create(bufferSize: 1)

  internal init(withSerial serial: String){
      self.scanDisposable = manager
          .scanFor([IT.instrumentType])
          .get(withSerial: serial)
          .take(1)
          .do(onNext: { (inst) in
              self.instrumentSubject.onNext(inst)
          })
          .subscribe()
}

И затем у меня есть ATSyncInteractor, который является public

public final class ATSyncInteractor<IT : InstrumentType> : ATCoreInteractor<IT> {
  public override init(withSerial serial: String) {
      super.init(withSerial: serial)
  }
}

public extension ATSyncInteractor where IT : InstrumentTypes.AT_1G_Wave {
  public func sync(opPriority: BLEOperationPriority = .normal, from: Date, to: Date, callback: @escaping (ATCoreReadyData<AT_1G_Wave_CurrentValues>?, [WaveTimeSeriesCoordinator], Error?) -> Void) {
    // DO SOMETHING
  }
}



let interactor = ATSyncInteractor<InstrumentTypes.AT_1G_Wave>(withSerial: "12345")

person Aleksander Aleksic    schedule 17.04.2018    source источник
comment
Как можно ожидать, что тип в другом модуле будет реализовывать InstrumentType, если он не может знать о ATCoreInstrumentProtocol?   -  person zneak    schedule 17.04.2018
comment
@zneak Они не предназначены для его реализации, но должны использовать его следующим образом: let interactor = ATSyncInteractor<InstrumentTypes.AT_1G_Wave>(withSerial: "12345")   -  person Aleksander Aleksic    schedule 17.04.2018
comment
Есть ли у ATCoreInstrumentProtocol связанные типы?   -  person zneak    schedule 17.04.2018
comment
@zneak Нет, нет.   -  person Aleksander Aleksic    schedule 17.04.2018
comment
Имеет ли общий параметр ATCoreInteractor большое значение в сигнатурах функций? Например, есть ли у вас функции, которые только принимают ATSyncInteractor<InstrumentTypes.AT_1G_Wave> вместо ATSyncIterator<IT>, где IT является общим?   -  person zneak    schedule 17.04.2018
comment
Я имею в виду, что, возможно, вам не нужен общий параметр для ATCoreInteractor. У вас может быть public enum, в котором перечислены InstrumentType и который может создавать конкретное значение каждого ASSOCIATED_INSTRUMENT.   -  person zneak    schedule 17.04.2018
comment
Если я вас правильно понял, то да. Возьмем, к примеру, функции public sync(...). Позже в этом году мы добавим AT_2G_Wave и AT_Wave_Plus InstrumentType, все они могут/будут иметь разные реализации sync(...).   -  person Aleksander Aleksic    schedule 17.04.2018
comment
У нас также будут ATPairingInteractor<IT: InstrumentType>, ATFirmwareInteractor<IT: InstrumentType>, ATSettingsInteractor<IT: InstrumentType> и так далее. Они также будут иметь разные реализации.   -  person Aleksander Aleksic    schedule 17.04.2018
comment
@zneak Я попробую ваше предложение Enum.   -  person Aleksander Aleksic    schedule 17.04.2018


Ответы (1)


Это оказалось моим решением.
InstrumentType содержит только SupportedInstrumentTypes.
ATCoreInteractor Больше не является общим, но наблюдатель относится к типу ATCoreInstrumentProtocol.
Расширения ATSyncInteractor приводят инструмент к связанному с ним типу.

Я открыт для улучшений и предложений.

public protocol InstrumentType : class {
    static var instrumentType: SupportedInstrumentTypes { get }
}

public final class InstrumentTypes {
    private init() {}

    public final class AT_1G_Wave : InstrumentType {
        private init() {}
        public class var instrumentType: SupportedInstrumentTypes { get { return .wave_1G } }
    }
}

public class ATCoreInteractor {

    internal var instrumentSubject = ReplaySubject<ATCoreInstrumentProtocol>.create(bufferSize: 1)

    internal init(for type: SupportedInstrumentTypes, withSerial serial: String){

        self.scanDisposable = manager
            .scanFor([type])
            .get(withSerial: serial)
            .take(1)
            .do(onNext: { (inst) in
                self.instrumentSubject.onNext(inst)
            })
            .subscribe()
    }
}

public final class ATSyncInteractor<IT : InstrumentType> : ATCoreInteractor {

    public init(withSerial serial: String) {
        super.init(for: IT.instrumentType, withSerial: serial)

    }
} 

public extension ATSyncInteractor where IT : InstrumentTypes.AT_1G_Wave {

    private func instrument() -> Observable<AT_1G_WaveInstrumentType> {
        return self.instrumentSubject.map { $0 as! AT_1G_WaveInstrumentType }
    }

    public func sync(opPriority: BLEOperationPriority = .normal, from: Date, to: Date, callback: @escaping (ATCoreReadyData<AT_1G_Wave_CurrentValues>?, [WaveTimeSeriesCoordinator], Error?) -> Void) {

    }
}
person Aleksander Aleksic    schedule 17.04.2018