Ich habe viele Gründe gesehen, warum das Entwerfen einer API mithilfe von Variablen anstelle von Funktionen problematisch ist und sich für mich wie eine Problemumgehung anfühlt, wenn ich berechnete Eigenschaften verwende. Es gibt gute Gründe, Ihre Instanzvariablen gekapselt zu halten. Hier habe ich ein Protokoll Automobile erstellt, dem Car entspricht. Dieses Protokoll verfügt über eine Zugriffsmethode, die ein Chassis-Objekt zurückgibt. Da das Auto dem entspricht, kann die RaceCar-Unterklasse es überschreiben und eine andere Chassis-Unterklasse zurückgeben. Dadurch kann die Car-Klasse auf eine Schnittstelle (Automobile) programmieren, und die RaceCar-Klasse, die sich mit RacingChassis auskennt, kann direkt auf die Variable _racingChassis zugreifen.
class Chassis {}
class RacingChassis: Chassis {}
protocol Automobile {
func chassis() -> Chassis
}
class Car: Automobile {
private var _chassis: Chassis
init () {
_chassis = Chassis()
}
func chassis() -> Chassis {
return _chassis
}
}
class RaceCar: Car {
private var _racingChassis: RacingChassis
override init () {
_racingChassis = RacingChassis()
super.init()
}
override func chassis() -> Chassis {
return _racingChassis
}
}
Ein weiteres Beispiel dafür, warum das Entwerfen einer API mithilfe von Variablen nicht funktioniert, ist, wenn Sie Variablen in einem Protokoll haben. Wenn Sie alle Protokollfunktionen in Erweiterungen aufteilen möchten, können Sie dies tun, außer dass gespeicherte Eigenschaften nicht in Erweiterungen platziert werden können und in der Klasse definiert werden müssen (damit diese kompiliert werden können, müssen Sie den Code auskommentieren AdaptableViewController-Klasse und entfernen Sie die Modusvariable aus der Erweiterung):
protocol Adaptable {
var mode: Int { get set }
func adapt()
}
class AdaptableViewController: UIViewController {
// var mode = 0
}
extension AdaptableViewController: Adaptable {
var mode = 0 // compiler error
func adapt() {
//TODO: add adapt code
}
}
Der obige Code hat den folgenden Compilerfehler: "Erweiterungen haben möglicherweise keine gespeicherten Eigenschaften". So können Sie das obige Beispiel neu schreiben, damit alles im Protokoll in der Erweiterung getrennt werden kann, indem Sie stattdessen Funktionen verwenden:
protocol Adaptable {
func mode() -> Int
func adapt()
}
class AdaptableViewController: UIViewController {
}
extension AdaptableViewController: Adaptable {
func mode() -> Int {
return 0
}
func adapt() {
// adapt code
}
}
strong
Eigenschaft ist und beim Versuch, sie zu überschreiben, ein Fehler aufgetreten ist. Es scheint jedoch, dass ich übersehen habe, dass dies zu einem "implizit ausgepackten optionalen" (chassis!
) in führt Schnell, alsooverride var chassis : Chassis!
behebt es.