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

How can you create an infix operator that applies to every class and struct?

我创建了一个 'configure' 中缀运算符“=>”,它允许我配置内联对象,允许我定义和初始化属性 and/or 在赋值时调用 methods/functions等级.

例如,而不是这个,它需要一个初始化器...

let redSquare = SquareView()

init(){ // Some init somewhere

    redSquare.backgroundColor = .red

}

我可以简单地做到这一点...

let redSquare = SquareView() => { [=12=].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 {}

Note: You could also implement this as a member function like below, but I prefer the infix operator as it doesn't clutter the . (dot) completion.

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 符合这个协议,但实际上,这应该可以被任何需要设置不通过初始化器传递的属性的东西使用,或者任何需要 method/function 作为其初始化的一部分被调用。

目前,这意味着我只需要继续在任何地方添加它(对于非基于 NSObject 的项目)...

extension MyStruct     : Configurable {}
extension MyClass      : Configurable {}
extension MyOtherClass : Configurable {}

这个是不允许的(这真让我烦恼!)

extension AnyObject : Configurable {}

例如,在 C# 中,您可以通过简单地扩展 'object' 来扩展所有内容,因为这是所有内容的基础(具有讽刺意味的是,包括值类型),但看起来 [=42 中没有任何相似之处=].

是否存在,或者我是否只需要继续手动添加这些一致性?

如果您想要的只是一个将闭包应用于您抛出的任何类型的运算符,那么这里的协议并不是真正正确的方法。一个普通的通用运算符(函数)就可以解决问题:

infix operator =>

@discardableResult func => <T>(this: T, _ delegate: (T) -> ()) -> T {
    delegate(this)
    return this
}

这可以完全按照您概述的方式使用,无需扩展任何内容。

I've created a 'configure' infix operator ...For instance, instead of this, which requires an initializer...

let redSquare = SquareView()
init(){ // Some init somewhere
    redSquare.backgroundColor = .red
}

I can simply do this...

let redSquare = SquareView() => { [=11=].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 }