Я разработчик iOS с парой опыта работы в swift, но редко использую PAT ...
На этот раз я пытался переместить некоторый код из приложения, которое яЯ разработал для общей библиотеки, которую я использую в нескольких проектах.В данном случае речь идет о фабрике, которая использует различные Builders (которые являются декораторами моих бизнес-ресурсов) через протокол Abstract Builder для получения элементов (в реальном случае ViewControllers).
Builder передает некоторые переменные, которыеФабрика переходит к нему, но они находятся на уровне приложения, поэтому, чтобы извлечь эту логику и поместить ее в мою библиотеку, мне нужно использовать общую ссылку, и, поскольку я хочу работать в режиме ориентированного на протокол программирования, этоAssociatedType.
// The item that i want to receive from my factory
protocol Item {
var content: String { get }
}
// This is the Builder interface that the Factory consumes
protocol Builder {
// The Abstract Parameters that the Application should define
associatedtype Parameters
func build(_ parameters: Parameters) -> Item?
}
// The BusinessResource of my library
protocol BusinessResource { }
// The Factory that consumes the Builders
protocol Factory {
associatedtype FactoryBuilder: Builder
var parameters: FactoryBuilder.Parameters { get }
func make(from businessResource: BusinessResource) -> Item?
}
// The generic implementation of my Factory
extension Factory {
func make(from businessResource: BusinessResource) -> Item? {
guard let builder = businessResource as? FactoryBuilder else {
return nil
}
return builder.build(self.parameters)
}
}
На данный момент все выглядит хорошо.
У меня есть два протокола, и они связаны между собой, разделяя общий тип, который является общим (параметры построителя).
Итак, на прикладном уровне теперь я могу представить свои конкретные параметры (я буду называть их ConcreteParameters XD)
// The concrete parameters of the Application Factory
struct ConcreteParameters {
let string: String
}
// The Builder interface restricting Parameters to ConcreteParameters
protocol BindedBuilder: Builder where Parameters == ConcreteParameters {
}
// The Factory interface restricting Parameters to ConcreteParameters
protocol BindedFactory: AbstractFactory where FactoryParameters: ConcreteParameters {
}
Пока все хорошо.Все выглядит на месте, и я начинаю думать, что это может сработать, поэтому теперь я пытаюсь реализовать конкретную Фабрику в приложении, чтобы попробовать, если это действительно работает.
// The concrete output of my Builder
struct ConcreteItem: Item {
var content: String
}
// The concrete BusinessResource that i get from my library
struct ConcreteObject: BusinessResource {
let string: String
}
// The decoration extension that makes ConcreteObject compliant with Builder
extension ConcreteObject: Builder {
typealias Parameters = ConcreteParameters
func build(_ parameters: ConcreteParameters) -> Item? {
return ConcreteItem(content: parameters.string + self.string)
}
}
// The real Factory inside my app
class ConcreteFactory: BindedFactory {
typealias FactoryBuilder = BindedBuilder
var parameters: ConcreteParameters {
return ConcreteParameters(string: "Hello ")
}
}
let item = ConcreteFactory().make(from: ConcreteObject(string: "world!"))
print(item ?? "NOT WORKING")
В этот момент что-то ломается ..Я получаю эту ошибку:
[ EDIT : ошибка возникла в предыдущей версии фрагмента, AbstractFactoriэто Фабрика ]
Это ошибка ??Я действительно не знаю, как решить это ...