2017-10-10 1 views
1

nehme ich eine Klassen A und B wie dieses:Zwingende berechnete Eigenschaft mit gespeicherten einer

class A { 
    var x: Int { return 9 } 
    func p() { print(x) } 
} 

class B: A { 
    ... 
} 

let v: A = B() 
v.p() 

Und ich dann x in B auf drei verschiedene Arten außer Kraft setzen:

class B: A { 

    // OPTION 1: FINE - prints 10 
    override var x: Int { return 10 } 

    // OPTION 2: ERROR - cannot override with a stored property 'x' 
    override var x = 10 

    // OPTION 3: FINE - prints 10 
    override lazy var x = 10 

} 

Kann mir jemand erklären, Was ist falsch beim Überschreiben einer berechneten Eigenschaft mit einer gespeicherten Eigenschaft, und warum wird alles plötzlich behoben, wenn ich es als faul deklariere?

Antwort

1

Es gibt keinen wirklichen technischen Grund, warum Sie eine Eigenschaft mit einer gespeicherten Eigenschaft nicht überschreiben können. Es verfügt über Getter und Setter (Accessoren), die die Zugriffsmethoden der zu überschreibenden Eigenschaft überschreiben können. Es sollte nur dem Überschreiben mit einer berechneten Eigenschaft entsprechen, die dann auf eine gespeicherte Eigenschaft weiterleitet.

Allerdings sehe ich eine leichte Komplikation mit dem Erlauben: Property Observer überschreibt.

Betrachten Sie das folgende Beispiel:

class C { 
    var f: Int { 
    get { return 5 } 
    set { print("C says f was set") } 
    } 
} 

class D : C { 
    override var f: Int { 
    didSet { 
     print("D says f was set") 
    } 
    } 
} 

let d = D() 
print(d.f) 
d.f = 7 
print(d.f) 

// 5 
// C says f was set 
// D says f was set 
// 5 

Wir können f ‚s didSet in D außer Kraft setzen. In diesem Fall wird override var f: Int im Wesentlichen als eine berechnete Eigenschaft mit einem Getter und Setter behandelt, der an super weiterleitet, mit einem zusätzlichen Aufruf an die didSet Implementierung im Setter.

Kein tatsächlicher Speicher wird von hier eingeführt. Warum ist das problematisch? Nun, wie würden wir dem Compiler sagen, dass wir eigentlich Speicher für f wollen? Das Hinzufügen eines Initialisierungsausdrucks (= 10) könnte das kommunizieren, aber nicht alle gespeicherten Eigenschaften haben Standardwerte; Die meisten werden vom Initialisierer der Klasse initialisiert. Wir würden wahrscheinlich ein Attribut irgendeiner Art benötigen, aber für solch einen begrenzten Anwendungsfall scheint es keine besonders nützliche Änderung der Sprache zu sein.

Der lazy Fall ist eindeutig, da wir keine Eigenschaftenbeobachter hinzufügen können.

Obwohl das alles gesagt wird, sollte der besondere Fall, den Sie präsentieren, auch klar geschnitten werden; Da die Basiseigenschaft nur einen Getter hat, müssen keine Eigenschaftsbeobachter überschrieben werden. Ich würde dir empfehlen, file a bug (hoffentlich) zu sehen, was das Swift-Team dazu zu sagen hat.

Sie können immer das gleiche Ergebnis mit einer berechneten Eigenschaft überschreiben erreichen, obwohl nach vorne auf eine gespeicherte Eigenschaft dann:

class C { 
    var f: Int { 
    return 9 
    } 
} 

class D : C { 

    private var _f: Int = 10 

    override var f: Int { 
    get { return _f } 
    set { _f = newValue } 
    } 
} 

let d = D() 
print(d.f) // 10 
d.f = 7 
print(d.f) // 7 
+1

Geschehen - https://bugs.swift.org/browse/SR-6165 – frangulyan

Verwandte Themen