代码之家  ›  专栏  ›  技术社区  ›  Mark A. Donohoe

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

  •  0
  • Mark A. Donohoe  · 技术社区  · 6 年前

    我已经创建了一个'configure'infix operator'=>'它允许我内联配置对象,允许我在赋值级别定义和初始化属性和/或调用方法/函数。

    例如,而不是这个,它需要一个初始值设定项。。。

    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 {}
    

    注意:您也可以将其实现为如下所示的成员函数,但我更喜欢中缀运算符,因为它不会使函数混乱(完成。

    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语言中,您可以通过简单地扩展“object”来扩展所有内容,因为这是所有内容的基础(讽刺的是,包括值类型),但Swift中似乎没有类似的内容。

    是有,还是我必须一直手动添加这些一致性?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Mark A. Donohoe    6 年前

    如果你想要的只是一个操作符,它将闭包应用于你抛出的任何类型,那么协议在这里并不是正确的方法。一个普通的泛型运算符(函数)将完成以下操作:

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

    这可以完全按照您的大纲使用,而不需要扩展任何内容。

        2
  •  0
  •   Community miroxlav    4 年前

    我创建了一个“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 }