斯威夫特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
限制。)
我想实现某种 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
限制。)