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

Swift 如何创建适用于每个类和结构的中缀运算符?,swift,swift-extensions,anyobject,Swift,Swift Extensions,Anyobject,我创建了一个“configure”infix操作符“=>”,它允许我在线配置对象,允许我在分配级别定义和初始化属性和/或调用方法/函数 例如,与此相反,它需要一个初始值设定项 let redSquare = SquareView() init(){ // Some init somewhere redSquare.backgroundColor = .red } let redSquare = SquareView() init(){ // Some init somewhere

我创建了一个“configure”infix操作符“=>”,它允许我在线配置对象,允许我在分配级别定义和初始化属性和/或调用方法/函数

例如,与此相反,它需要一个初始值设定项

let redSquare = SquareView()

init(){ // Some init somewhere

    redSquare.backgroundColor = .red

}
let redSquare = SquareView()
init(){ // Some init somewhere
    redSquare.backgroundColor = .red
}
我可以简单地做到这一点

let redSquare = SquareView() => { $0.backgroundColor = .red }
let redSquare = SquareView() => { $0.backgroundColor = .red }
“配置”操作符的实现方式如下

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 {}
注意:您也可以像下面这样将其实现为成员函数,但我更喜欢中缀运算符,因为它不会使整个过程变得混乱。点完成

如您所见,我已经使NSObject符合此协议,但实际上,任何需要设置未通过初始值设定项的属性的对象,或任何需要在初始化过程中调用方法/函数的对象,都可以使用此协议

目前,这意味着我只需要在任何地方为非基于NSObject的项目添加此项

extension MyStruct     : Configurable {}
extension MyClass      : Configurable {}
extension MyOtherClass : Configurable {}
这是不允许的,真让我恼火

extension AnyObject : Configurable {}
例如,在C中,您可以通过简单地扩展“object”来扩展所有内容,因为具有讽刺意味的是,这是所有内容(包括值类型)的基础,但Swift中似乎没有类似的内容


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

如果您只需要一个运算符将闭包应用于您抛出的任何类型,那么协议实际上不是正确的方法。普通的泛型运算符函数将实现以下功能:

infix operator =>

@discardableResult func => <T>(this: T, _ delegate: (T) -> ()) -> T {
    delegate(this)
    return this
}
这可以完全按照您概述的方式使用,而无需扩展任何内容

我已经创建了一个“配置”中缀运算符…例如,它需要一个初始值设定项,而不是这个

let redSquare = SquareView()

init(){ // Some init somewhere

    redSquare.backgroundColor = .red

}
let redSquare = SquareView()
init(){ // Some init somewhere
    redSquare.backgroundColor = .red
}
我可以简单地做到这一点

let redSquare = SquareView() => { $0.backgroundColor = .red }
let redSquare = SquareView() => { $0.backgroundColor = .red }
不需要新的接线员。Swift中已存在此功能;它被称为闭包匿名函数:

 let redSquare : SquareView = {
      let sv = SquareView()
      sv.backgroundColor = .red
      return sv
 }()
在NSObject派生的情况下,编译器可以保证init的存在,您可以使用我的lend实用程序压缩表示法:


我不知道您可以在全局级别定义运算符。我以为你必须把它当作一个静态的类型。这太完美了!我喜欢错过如此明显的事情!谢谢必须做一个小的改变,因为使用这种方法,理论上你们可以传递选项的显式或隐式展开,这会导致返回问题。用这种方法解决这个问题。好的思考,我没有考虑选择。操作符也可以被标记为rethrowing,以防有人希望允许可能抛出错误的配置,但这在这个用例中可能不太相关。为什么这是一个IUO参数?这些都已弃用,传入nil将崩溃,因为返回了非可选的T。您确定吗?因为T来自于参数本身,所以如果T本身是可选的或IUO,那么它可以是nil,这意味着它本身是可选的,这样它就不会崩溃。也就是说,如果它是可选的IUO,则它只能为零。有道理吗?嗨,马特!你以前回答过我很多问题。谢谢关于带闭包的中缀方法,我更喜欢的一点是后者只在初始化时起作用。前者可以在任何时候工作,包括当您已经有一个实例时。比如说哈!!,如果我已经有了一个RedSquare,我仍然可以使用myRedSquare=>{.$0.bla;$0.blabla},这样可以节省大量的输入,更不用说在设置一组属性或调用方法时获得免费的作用域了,如果需要的话,你可以传递内联,因为这是一个语句。当然,这是一个很好的观点。我是按照你引用的特定用例来做的。你想让我把这个留在这里吗?如果不相关,我可以删除它。不,相关!有些人可能只需要初始化时间。此外,您的“借出”功能可能会帮助他人。我认为这增加了话题!