Protokoll-Erweiterung-Initialisierer
Ich würde gerne wissen, was das Protokoll entspricht ist für eine Initialisierung in eine einfache Klasse, die nur enthält die Initialisierung Funktionalität und soll nur verlängert werden in einer konkreten Klasse.
Also wahrscheinlich der einfachste Weg zu zeigen, den code - ich freu mich für die Protokoll-Erweiterung äquivalent zu der folgenden:
import UIKit
class Thing {
var color:UIColor
init(color:UIColor) {
self.color = color
}
}
class NamedThing:Thing {
var name:String
init(name:String,color:UIColor) {
self.name = name
super.init(color:color)
}
}
var namedThing = NamedThing(name: "thing", color: UIColor.blueColor())
Erwartete ich den code so Aussehen:
protocol Thing {
var color:UIColor {get set}
}
extension Thing {
init(color:UIColor) {
self.color = color
}
}
class NamedThing:Thing {
var name:String
var color:UIColor
init(name:String,color:UIColor) {
self.name = name
self.init(color:color)
}
}
Ich gesehen habe Lösungen vorgeschlagen, die in anderen StackOverflow-Fragen(zB. Wie definieren-Initialisierungen in eine Protokoll-Erweiterung? ), aber ich bin mir nicht sicher, Sie arbeiten noch speziell auf das problem von zusätzlichen Parametern in die Klasse Initialisierung.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie eine gültige Kette von init für die Erstellung einer Instanz einer Klasse und das schränkt Ihre Optionen für die Initialisierungen in den Protokollen.
Seit Ihr Protokoll können nicht sicher sein, um alle Mitglieder der Klasse, der es verwendet, jeder Initialisierung erklären Sie in Ihrem Protokoll müssen delegieren Initialisierung des "unbekannten" Mitglieder der Klasse zu einer anderen Initialisierung zur Verfügung gestellt, die von der Klasse selbst.
Ich angepasst, Ihrem Beispiel zu illustrieren dies mit einem einfachen init() die delegation Initialisierer für das Protokoll.
Wie Sie sehen können, dies erfordert, dass Sie Ihre Klasse implementieren, die ursprünglichen Werte für alle Mitglieder, wenn init() aufgerufen wird. In diesem Fall hatte ich das, indem default-Werte in den einzelnen Mitgliedstaaten in der Erklärung. Und da gibt es nicht immer eine tatsächliche Startwert für einige Mitglieder, änderte ich Sie auf auto-unwrap Optionen.
Zu machen und denkt mehr interessant, Ihre Klasse kann nicht delegieren die Initialisierung eines Protokolls geliefert Initialisierer, es sei denn, er tut dies durch einen Komfort-Initialisierer.
Ich Frage mich, ob all diese Einschränkungen sind der Mühe Wert. Ich vermute, Sie versuchen, verwenden Sie ein Protokoll, weil Sie eine Reihe von gemeinsamen Variablen initialisiert werden konsequent zwischen Klassen, das Protokoll umzusetzen. Vielleicht mit einem delegate-Klasse wäre eine einfacherer Lösung als die Protokolle (nur ein Gedanke).
Genial, keine Probleme.
Nicht. Das ist nie zur Arbeit gehen. Dieser bricht Weg, zu viele Regeln. Die erste und wichtigste ist, dass das nicht notwendigerweise alle Eigenschaften. Betrachten Sie Ihre
NamedThing
. Was istname
in diesem Fall? Was passiert, wenn diecolor
setter holt andere Eigenschaften wurden noch nicht festgelegt noch? Der compiler kann nicht sehen, jede mögliche Umsetzung dieses doch, so hat es keine Ahnung, obcolor
ist nur ein ivar oder etwas Wild komplizierter. Nein, es ist nicht zur Arbeit gehen.Das eigentliche problem ist "eine abstrakte Klasse, die erweitert werden kann, die in einer konkreten Klasse." Vergessen Klassen. Vergessen Vererbung. Swift ist alles über die Zusammensetzung und Protokolle, nicht Vererbung.
Denken wir also über das Beispiel, das Sie beschreiben in den Kommentaren (obwohl in den Kakao, es gibt keine "abstrakte Klassen", entweder). Nehmen wir an, dass die Einstellung Farbe ist in der Tat eine Menge von code, die Sie nicht duplizieren möchten. Das ist kein problem. Sie brauchen nur eine Funktion.
Da der Punkt der Erweiterung ist zu handhaben teilweise Initialisierung, lass es einfach zu berechnen, der Teil, den Sie brauchen. Versuchen Sie nicht, machen es zu einer Initialisierung in eine Verlängerung, da hätte es sich dann verantwortlich für das initialisieren alles, und das ist sehr schwer zu tun korrekt, wenn Sie mischen Sie es mit der Vererbung.
UIGestureRecognizer
?) Ich vermute stark, dass das eigentliche problem, dem Sie gegenüberstehen, ist viel mehr leicht gelöst werden, einen anderen Weg. Das ist das klassische problem mit über-Vereinfachung der Frage.init?(colorCode: String) { guard let color = NamedThing.colorFor(code: colorCode) else { return nil }; self.color = color }
.Hier ist, was ich im Sinn hatte, für die "delegate-Klasse".
Es ist eine Technik, die ich verwenden zum hinzufügen von gespeicherten Variablen zu einer Klasse mithilfe von Protokollen.
Ich zu dem Schluss gekommen, dass die Frage ist irgendwie nicht zu beantworten, als eine Protokoll-Erweiterung kann nicht dynamisch definieren Sie die Eigenschaften(es sei denn, es gibt Standardwerte für Eigenschaften, oder deklariert Sie als implizit unwrapped). Zum beheben dieses in eine weitere Protokoll-orientierte Mode, es erfordert eine andere Herangehensweise, die immer noch mit sich bringt deklarieren und initialisieren aller Variablen in der konkreten Klasse, so etwas wie:
Danke an @alain-t für die Antwort, ich werde akzeptieren, weil es am ehesten eine Lösung gefunden zu meiner Frage, trotz, einschließlich implizit unwrapped Eigenschaften.
Danke an @rob-napier auch für Ihren Beitrag auch.