Анонимный класс в swift

есть ли эквивалентный синтаксис или техника для анонимного класса в Swift? Просто для уточнения анонимного класса в примере Java здесь -http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html

спасибо!

5 ответов


насколько я знаю, эквивалентного синтаксиса нет.

что касается эквивалентных методов, теоретически вы можете использовать замыкания и определять структуры и классы внутри них. К сожалению, я не могу заставить это работать на игровой площадке или проекте, не заставляя его рухнуть. Скорее всего, это не готово к использованию в текущей бета-версии.

что-то вроде...

protocol SomeProtocol {
    func hello()
}

let closure : () -> () = {
    class NotSoAnonymousClass : SomeProtocol {
        func hello() {
            println("Hello")
        }
    }
    let object = NotSoAnonymousClass()
    object.hello()
}

...в настоящее время выводит эту ошибку:

invalid linkage type for global declaration
%swift.full_heapmetadata* @_TMdCFIv4Test7closureFT_T_iU_FT_T_L_19NotSoAnonymousClass
LLVM ERROR: Broken module found, compilation aborted!
Command /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 1

например, шаблон Java listener / adapter будет переведен на Swift следующим образом:

protocol EventListener {
    func handleEvent(event: Int) -> ()
}

class Adapter : EventListener {
    func handleEvent(event: Int) -> () {
    }
}

var instance: EventListener = {
    class NotSoAnonymous : Adapter {
        override func handleEvent(event: Int) {
            println("Event: \(event)")
        }
    }

    return NotSoAnonymous()
}()

instance.handleEvent(10)

(сбой компилятора на бета-2)

проблема в том, что вам всегда нужно указать имя. Я не думаю, что Apple когда-либо представит анонимные классы (и структуры и т. д.) потому что было бы довольно сложно прийти с синтаксисом, который не сталкивается с конечными замыканиями.

также в программировании анонимных вещей плохо. Именование вещей помогает читателям чтобы понять код.


вы также можете создать простой пустой класс, который действует как голый протокол, и передать конец init функция, которая переопределяет все, что вы хотите, как это:

class EmptyClass {

    var someFunc: () -> () = { }

    init(overrides: EmptyClass -> EmptyClass) {
        overrides(self)
    }
}

// Now you initialize 'EmptyClass' with a closure that sets
// whatever variable properties you want to override:

let workingClass = EmptyClass { ec in
    ec.someFunc = { println("It worked!") }
    return ec
}

workingClass.someFunc()  // Outputs: "It worked!"

технически это не "анонимно", но работает одинаково. Вам дается пустая оболочка класса, а затем вы заполняете ее или переопределяете любые параметры, которые вы хотите, когда инициализируете ее с закрытием.

это в основном то же самое, за исключением вместо выполнения ожиданий протокол, он переопределяет свойства класса.


нет синтаксиса анонимного класса в Swift. Но вы можете создать класс внутри класса и методов класса:

class ViewController: UIViewController {

    class anonymousSwiftClass {
        func add(number1:Int, number2:Int) -> Int {
            return number1+number2;
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        class innerSwiftClass {
            func sub(number1:Int, number2:Int) -> Int {
                return number1-number2;
            }
        }

        var inner = innerSwiftClass();
        println(inner.sub(2, number2: 3));

        var anonymous = anonymousSwiftClass();
        println(anonymous.add(2, number2: 3));
    }
}

Это то, что я закончил делать (шаблон наблюдателя). Вы можете использовать закрытие аналогичным образом, вы бы использовали анонимные классы в Java. С очевидными ограничениями, конечно.

class Subject {
   // array of closures
   var observers: [() -> Void] = []

   // @escaping says the closure will be called after the method returns
   func register(observer: @escaping () -> Void) {
       observers.append(observer)
   }

   func triggerEvent() {
       observers.forEach { observer in
            observer()
       }
   }
}

var subj = Subject()
// you can use a trailing closure
subj.register() {
    print("observerd")
}

// or you can assign a closure to a variable so you can maybe use the reference to removeObserver() if you choose to implement that method
var namedObserver: () -> Void = {
    print("named observer")
}
subj.register(observer: namedObserver)

subj.triggerEvent()
// output:
// observerd
// named observer