Я хотел бы реализовать какой-нибудь шаблон Decorator
, который позволяет писать многоразовые декораторы
Итак, я определил 2 протокола.Первый определяет тип для декоратора:
protocol ViewDecorator {
associatedtype View: Decoratable
func decorate(view: View)
}
// this is how I expect to use decorator
class GreenViewDecorator: ViewDecorator {
typealias View = GreenView
func decorate(view: GreenView) {
view.backgroundColor = UIColor.green
}
}
Второй определяет тип, которому decoratable представление должно соответствовать.
protocol Decoratable {
func decorate<T: ViewDecorator>(with decorator: T)
}
extension Decoratable where Self: UIView {
func decorate<T : ViewDecorator>(with decorator: T) {
decorator.decorate(view: self)
}
}
// exampled of 'decoratable' view
class GreenView: UIView, Decoratable { }
Я определил по умолчаниюреализация функции func decorate<T : ViewDecorator>(with decorator: T)
в расширении протокола.Я вижу, это полезно, если мой взгляд будет реализовывать метод по умолчанию.Мне просто нужно только наследовать Decoratable
протокол.И тогда я могу использовать его так:
// example of using decorator with view
let decorator = GreenViewDecorator()
greenView.decorate(with: decorator)
Но компилятор Swift5 выдает ошибку в строке decorator.decorate(view: self)
Невозможно вызвать 'decorate' со списком аргументовtype '(view: Self)'
============== TOTAL LISTING ==========
protocol ViewDecorator {
associatedtype View: Decoratable
func decorate(view: View)
}
protocol Decoratable {
func decorate<T: ViewDecorator>(with decorator: T)
}
extension Decoratable where Self: UIView {
func decorate<T : ViewDecorator>(with decorator: T) {
decorator.decorate(view: self)
}
}
class GreenView: UIView, Decoratable { }
class GreenViewDecorator: ViewDecorator {
typealias View = GreenView
func decorate(view: GreenView) {
view.backgroundColor = UIColor.green
}
}
class ViewController: UIViewController {
@IBOutlet var greenView: GreenView!
override func viewDidLoad() {
super.viewDidLoad()
let decorator = GreenViewDecorator()
greenView.decorate(with: decorator)
}
}