Как сохранить PAT или проблему наследования классов? - PullRequest
2 голосов
/ 24 января 2020

Я опишу структуру, с которой я сейчас работаю. Проект основан на следующем PAT:

@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
public protocol ProducerOperationProtocol: NSOperation {

  associatedtype Output
  associatedtype Failure: Error
  associatedtype Condition: OperationCondition
  associatedtype Observer: OperationObserver


  typealias Produced = Result<Output, ProducerOperation<Output, Failure>.Error>

  var produced: Produced? { get }


  var condition: Condition { get }

  var observer: Observer { get }


  func willEnqueue()

  func execute()

  func finish(with produced: Produced)

  func finished(with produced: Produced)


  func produce<O: ProducerOperationProtocol>(new operation: O)


  func recieve(completion: @escaping (Produced) -> Void)
}

и двух сопровождающих PATS:

@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
public protocol OperationCondition {

  associatedtype Operation: ProducerOperationProtocol
  associatedtype Failure: Error


  var isMutuallyExclusive: Bool { get }


  func dependency<O: ProducerOperationProtocol>(for operation: Operation) -> O?

  func evaluate(for operation: Operation, completion: @escaping (Result<Void, Failure>) -> Void)
}


@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
public protocol OperationObserver {

  associatedtype Operation: ProducerOperationProtocol


  func operationDidStart(_ operation: Operation)

  func operation<NewOperation: ProducerOperationProtocol>(_ operation: Operation, didProduce newOperation: NewOperation)

  func operationDidCancel(_ operation: Operation)

  func operationDidFinish(_ operation: Operation)
}

А затем наступает большое разочарование:

@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
open class ProducerOperation<Output, Failure: Error>: Operation, ProducerOperationProtocol {

  public typealias Output = Output
  public typealias Failure = Failure

  // ...

  // How to store Condition 
  // var condition: Condition { get } ???

  // ...

  // How to store Observers
  // var observer: Observer { get } ???
}

I ' Я постараюсь объяснить, что здесь происходит. У меня есть два класса стирания типов:

@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
public struct AnyOperationCondition<Operation: ProducerOperationProtocol>

@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
public struct AnyOperationObserver<Operation: ProducerOperationProtocol>

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

private let _condition: AnyOperationCondition<Self>
open private(set) condition: some OperationCondition { _condition }

private let _observer: AnyOperationObserver<Self>
open private(set) observer: some OperationObserver { _observer }

Но мне все равно нужно как-то их хранить и указать конкретный подкласс c. Я также не могу сделать стирание типа для основного класса, потому что он унаследован от класса и соответствует PAT.

Снова. Мне нужно хранить условия и наблюдателей внутри класса, но я не знаю, как это сделать, потому что класс может быть унаследован.

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

@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
public protocol OperationObserver {

  func operationDidStart<O: ProducerOperationProtocol>(_ operation: O)

  func operation<O: ProducerOperationProtocol, NewOperation: ProducerOperationProtocol>(_ operation: O, didProduce newOperation: NewOperation)

  func operationDidCancel<O: ProducerOperationProtocol>(_ operation: O)

  func operationDidFinish<O: ProducerOperationProtocol>(_ operation: O)
}
...