我创建了一个'configure'中缀运算符'=>',它使我可以内联配置对象,从而使我能够在分配级别定义和初始化属性和/或调用方法/函数。
例如,与其相反,它需要一个初始化程序...
let redSquare = SquareView()
init(){ // Some init somewhere
redSquare.backgroundColor = .red
}
我可以简单地做到这一点...
let redSquare = SquareView() => { $0.backgroundColor = .red }
'configure'运算符是这样实现的...
infix operator =>
public protocol Configurable {}
extension Configurable {
public typealias ConfigureDelegate = (Self) -> Void
@discardableResult
public static func => (this:Self, _ delegate:ConfigureDelegate) -> Self {
delegate(this)
return this
}
}
extension NSObject : Configurable {}
注意:您也可以将其实现为如下所示的成员函数,但我更喜欢infix运算符,因为它不会使混乱。 (点)完成。
public protocol Configurable {}
extension Configurable {
public typealias ConfigureDelegate = (Self) -> Void
@discardableResult
public func configure(delegate:ConfigureDelegate) -> Self {
delegate(self)
return self
}
}
extension NSObject : Configurable {}
如您所见,我已经使NSObject符合此协议,但是实际上,应该将其设置为需要设置未通过初始化程序传递的属性的任何对象,或需要将方法/函数作为对象的任何对象。被称为初始化的一部分。
当前,这意味着我只需要继续将其添加到所有位置(对于非基于NSObject的项目)...
extension MyStruct : Configurable {}
extension MyClass : Configurable {}
extension MyOtherClass : Configurable {}
这是不允许的(这真让我烦恼!)
extension AnyObject : Configurable {}
例如,在C#中,您可以通过简单地扩展“对象”来扩展所有内容,因为这是所有内容的基础(具有讽刺意味的是,包括值类型),但是在Swift中看起来并没有类似之处。
是在那里,还是我只需要继续手动添加这些一致性?
答案 0 :(得分:1)
如果您想要的只是一个运算符,该运算符将闭包应用于您向其抛出的任何类型,那么协议在这里并不是真正的正确方法。一个普通的通用运算符(函数)就可以解决问题:
infix operator =>
@discardableResult func => <T>(this: T, _ delegate: (T) -> ()) -> T {
delegate(this)
return this
}
这可以按照您概述的方式使用,而无需扩展任何内容。
答案 1 :(得分:0)
我已经创建了一个'configure'中缀运算符...例如,代替它,它需要一个初始化程序...
let redSquare = SquareView() init(){ // Some init somewhere redSquare.backgroundColor = .red }
我可以简单地做到这一点...
let redSquare = SquareView() => { $0.backgroundColor = .red }
不需要新的运算符。这个功能已经在Swift中存在了。这叫做闭包(匿名函数):
let redSquare : SquareView = {
let sv = SquareView()
sv.backgroundColor = .red
return sv
}()
对于NSObject派生类,其中保证编译器存在init()
,则可以使用我的lend
实用程序来压缩表示法:
func lend<T> (_ closure: (T)->()) -> T where T:NSObject {
let orig = T()
closure(orig)
return orig
}
因此:
let redSquare = lend { (sv:SquareView) in sv.backgroundColor = .red }