Tendo a mettere solo le necessità (proprietà memorizzate, inizializzatori) nelle definizioni della mia classe e spostare tutto il resto nel loro extension
, un po 'come un extension
blocco logico con cui raggrupperei // MARK:
.
Per una sottoclasse di UIView, ad esempio, finirei con un'estensione per le cose relative al layout, una per la sottoscrizione e la gestione degli eventi e così via. In queste estensioni, devo inevitabilmente sostituire alcuni metodi UIKit, ad es layoutSubviews
. Non ho mai notato problemi con questo approccio - fino ad oggi.
Prendi ad esempio questa gerarchia di classi:
public class C: NSObject {
public func method() { print("C") }
}
public class B: C {
}
extension B {
override public func method() { print("B") }
}
public class A: B {
}
extension A {
override public func method() { print("A") }
}
(A() as A).method()
(A() as B).method()
(A() as C).method()
L'output è A B C
. Questo ha poco senso per me. Ho letto che le estensioni di protocollo vengono inviate staticamente, ma questo non è un protocollo. Questa è una classe regolare e mi aspetto che le chiamate di metodo vengano inviate in modo dinamico in fase di esecuzione. Chiaramente la chiamata C
deve essere almeno spedita e prodotta in modo dinamico C
?
Se rimuovo l'eredità da NSObject
e creo C
una classe root, il compilatore si lamenta dicendo declarations in extensions cannot override yet
, di cui ho già letto. Ma come NSObject
cambia le cose come avere una classe radice?
Spostare entrambe le sostituzioni nella loro dichiarazione di classe produce A A A
come previsto, spostando solo B
i prodotti A B B
, spostando solo A
i prodotti C B C
, l'ultimo dei quali non ha assolutamente senso per me: nemmeno quello tipicamente statico A
produce più l' A
output!
Aggiungere la dynamic
parola chiave alla definizione o una sostituzione sembra darmi il comportamento desiderato "da quel punto nella gerarchia delle classi verso il basso" ...
Cambiamo il nostro esempio in qualcosa di un po 'meno costruito, ciò che in realtà mi ha fatto pubblicare questa domanda:
public class B: UIView {
}
extension B {
override public func layoutSubviews() { print("B") }
}
public class A: B {
}
extension A {
override public func layoutSubviews() { print("A") }
}
(A() as A).layoutSubviews()
(A() as B).layoutSubviews()
(A() as UIView).layoutSubviews()
Ora capiamo A B A
. Qui non posso rendere dinamico il layout di UIViewSubviews in alcun modo.
Spostare entrambe le sostituzioni nella loro dichiarazione di classe ci A A A
riacquista, solo le A o le B ci ottengono ancora A B A
. dynamic
risolve di nuovo i miei problemi.
In teoria, potrei aggiungere dynamic
tutto ciò override
che faccio, ma sento che sto facendo qualcos'altro qui.
È davvero sbagliato usare extension
s per raggruppare il codice come faccio io?