Как вы можете создать инфиксный оператор, который применяется к каждому классу и структуре? - PullRequest
0 голосов
/ 13 октября 2018

Я создал инфиксный оператор 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 {}

Примечание. Вы также можете реализовать это как функцию-член, как показано ниже, но я предпочитаю инфиксный оператор, поскольку он не загромождает.(точка) завершение.

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 голосов
/ 17 октября 2018

Я создал инфиксный оператор '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 }
0 голосов
/ 17 октября 2018

Если все, что вам нужно, это оператор, который применяет замыкание к любому типу, который вы к нему добавляете, то протокол здесь не совсем правильный подход.Простой универсальный оператор (функция) сделает свое дело:

infix operator =>

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

Это может быть использовано точно так, как вы обрисовали, без необходимости расширять что-либо.

...