斯威夫特5。协议扩展引发编译错误 'Cannot invoke function with an argument list of type Self'

Swift5. Protocol extension raises compilation error 'Cannot invoke function with an argument list of type Self'

我想实现某种 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)

行引发错误

Cannot invoke 'decorate' with an argument list of 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)
        }
    }

参数的类型是关联类型 View,但尚未确定 Self 是那种类型,因此您不能传递类型 Self 的参数没有确定它是兼容的。例如:

extension Decoratable where Self: UIView {
    func decorate<T: ViewDecorator>(with decorator: T) where T.View == Self {
        decorator.decorate(view: self)
    }
}

(但是,如果你这样做,你将难以遵守 Decoratable 协议,因为它需要此方法用于 any ViewDecorator。你可以更改协议也具有相同的 T.View == Self 限制。)