如何创建适用于每个类和结构的中缀运算符?

时间:2018-10-13 04:05:39

标签: swift swift-extensions anyobject

我创建了一个'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中看起来并没有类似之处。

是在那里,还是我只需要继续手动添加这些一致性?

2 个答案:

答案 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 }
相关问题