Frage

Dies ist ein relativ häufiges Entwurfsmuster:

https://stackoverflow.com/a/17015041/743957

Es ermöglicht Ihnen, eine Unterklasse von Ihrem zurückzugeben init Anrufe.

Ich versuche herauszufinden, wie ich mit Swift am besten dasselbe erreichen kann.

Ich weiß, dass es mit Swift höchstwahrscheinlich eine bessere Methode gibt, dasselbe zu erreichen.Allerdings wird meine Klasse von einer vorhandenen Obj-C-Bibliothek initialisiert, über die ich keine Kontrolle habe.Es muss also auf diese Weise funktionieren und von Obj-C aus aufrufbar sein.

Für Hinweise wäre ich sehr dankbar.

War es hilfreich?

Lösung

Ich glaube nicht, dass dieses Muster direkt in SWIFT unterstützt werden kann, da Initialisierer keinen Wert, da sie nicht in objektiven C zurückgibt, und so erhalten Sie keine Gelegenheit, eine alternative Objektinstanz zurückzugeben.

Sie können ein Typ-Methode als Objektfabrik verwenden - ein ziemlich aufgeschlossenes Beispiel ist -

generasacodicetagpre.

main.swift

generasacodicetagpre.

Andere Tipps

Die "swimmzige" Möglichkeit, Klassencluster zu erstellen, wäre eigentlich, ein Protokoll anstelle einer Basisklasse freizulegen.

scheinbar verbietet der Compiler statische Funktionen auf Protokollen oder Protokollerweiterungen.

bis z. https://github.com/apple/swift-evolution/pull/247 (Fabrikinstitiminitialisierer) wird akzeptiert und umgesetzt, der einzige Weg, den ich dazu finden könnte, dies zu tun, ist das Folgende:

generasacodicetagpre.

.

generasacodicetagpre.

Seit init() gibt keine Werte zurück wie -init In Objective C scheint die Verwendung einer Factory-Methode die einfachste Option zu sein.

Ein Trick besteht darin, Ihre Initialisierer als zu markieren private, so was:

class Person : CustomStringConvertible {
    static func person(age: UInt) -> Person {
        if age < 18 {
            return ChildPerson(age)
        }
        else {
            return AdultPerson(age)
        }
    }

    let age: UInt
    var description: String { return "" }

    private init(_ age: UInt) {
        self.age = age
    }
}

extension Person {
    class ChildPerson : Person {
        let toyCount: UInt

        private override init(_ age: UInt) {
            self.toyCount = 5

            super.init(age)
        }

        override var description: String {
            return "\(self.dynamicType): I'm \(age). I have \(toyCount) toys!"
        }
    }

    class AdultPerson : Person {
        let beerCount: UInt

        private override init(_ age: UInt) {
            self.beerCount = 99

            super.init(age)
        }

        override var description: String {
            return "\(self.dynamicType): I'm \(age). I have \(beerCount) beers!"
        }
    }
}

Dies führt zu folgendem Verhalten:

Person.person(10) // "ChildPerson: I'm 10. I have 5 toys!"
Person.person(35) // "AdultPerson: I'm 35. I have 99 beers!"
Person(35) // 'Person' cannot be constructed because it has no accessible initializers
Person.ChildPerson(35) // 'Person.ChildPerson' cannot be constructed because it has no accessible initializers

Es ist seitdem nicht ganz so schön wie Objective C private bedeutet, dass alle Unterklassen in derselben Quelldatei implementiert werden müssen, und es gibt den geringfügigen Syntaxunterschied Person.person(x) (oder Person.create(x) oder was auch immer) statt einfach Person(x), aber praktisch gesehen funktioniert es genauso.

Um buchstäblich als instanziieren zu können Person(x), du könntest dich umdrehen Person in eine Proxy-Klasse, die eine private Instanz der eigentlichen Basisklasse enthält und alles an diese weiterleitet.Ohne Nachrichtenweiterleitung funktioniert dies für einfache Schnittstellen mit wenigen Eigenschaften/Methoden, wird aber für alles, was komplexer ist, unhandlich :P

Ich denke, eigentlich kann das Cluster-Muster mit Laufzeitfunktionen in Swift implementiert werden.Der Hauptpunkt ist, die Klasse Ihres neuen Objekts bei der Initialisierung durch eine Unterklasse zu ersetzen.Der untenstehende Code funktioniert gut, obwohl ich denke, dass mehr Aufmerksamkeit auf die Initialisierung der Unterklasse gezahlt werden sollte.

generasacodicetagpre.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top