web-dev-qa-db-fra.com

Classe anonyme en swift

Existe-t-il une syntaxe ou une technique équivalente pour la classe anonyme dans Swift? Juste pour clarification. Exemple de la classe anonyme en Java - http://docs.Oracle.com/javase/tutorial/Java/javaOO/anonymousclasses.html

Merci!

29
eranh

Pour autant que je sache, il n'y a pas de syntaxe équivalente.

En ce qui concerne les techniques équivalentes, vous pouvez théoriquement utiliser des fermetures et définir des structures et des classes à l'intérieur de celles-ci. Malheureusement, je ne peux pas obtenir que cela fonctionne dans une cour de récréation ou un projet sans le faire planter. Ce n'est probablement pas prêt à être utilisé dans la version bêta actuelle.

Quelque chose comme...

protocol SomeProtocol {
    func hello()
}

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

... affiche actuellement cette erreur:

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
13
hpique

Vous pouvez également créer une classe vide de base qui agit comme un protocole nu et transmettre une fermeture à la fonction init qui remplace tout ce que vous voulez, comme ceci:

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!"

Ce n'est pas techniquement "anonyme" mais cela fonctionne de la même manière. On vous donne un Shell vide d'une classe, puis vous le remplissez ou vous substituez les paramètres de votre choix lorsque vous l'initialisez avec une fermeture.

C'est fondamentalement la même chose, à la différence qu'au lieu de répondre aux attentes d'un protocole, il est prioritaire sur les propriétés d'une classe.

11
Aaron Rasmussen

Par exemple, le modèle d'écouteur/adaptateur Java serait traduit en Swift de la manière suivante:

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)

(Crashing le compilateur sur Beta 2)

Le problème est que vous devez toujours spécifier un nom. Je ne pense pas qu'Apple introduira jamais des classes anonymes (et des structs, etc.), car il serait assez difficile d'avoir une syntaxe qui n'entre pas en conflit avec les fermetures de fin.

Aussi, en programmation, les choses anonymes sont mauvaises. Nommer des choses aide les lecteurs à comprendre le code.

9
Sulthan

Aucune syntaxe de classe anonyme dans Swift. Mais, vous pouvez créer une classe dans une classe et des méthodes de classe:

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));
    }
}
7

C'est ce que j'ai fini par faire (modèle Observer). Vous pouvez utiliser les fermetures de la même manière que les classes anonymes en Java. Avec des limites évidentes bien sûr.

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
0