Tiendo a poner solo las necesidades (propiedades almacenadas, inicializadores) en las definiciones de mi clase y mover todo lo demás a las suyas extension, como un extensionbloque lógico con el que también agruparía // MARK:.
Para una subclase de UIView, por ejemplo, terminaría con una extensión para cosas relacionadas con el diseño, una para suscribirse y manejar eventos, etc. En estas extensiones, inevitablemente tengo que anular algunos métodos UIKit, por ejemplo layoutSubviews. Nunca noté ningún problema con este enfoque, hasta hoy.
Tome esta jerarquía de clases, por ejemplo:
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()
La salida es A B C. Eso tiene poco sentido para mí. Leí sobre las Extensiones de protocolo que se envían estáticamente, pero este no es un protocolo. Esta es una clase regular, y espero que las llamadas a métodos se envíen dinámicamente en tiempo de ejecución. ¿Está claro que la llamada Cal menos debería ser despachada y producida dinámicamente C?
Si elimino la herencia NSObjecty hago Cuna clase raíz, el compilador se queja diciendo declarations in extensions cannot override yet, sobre lo que ya leí. ¿Pero cómo tener NSObjectcomo clase raíz cambia las cosas?
Mover ambas anulaciones en su declaración de clase produce A A Acomo se esperaba, mover solo Blas producciones A B B, mover solo Alas producciones C B C, la última de las cuales no tiene absolutamente ningún sentido para mí: ¡ni siquiera la que está escrita estáticamente para Aproducir la Asalida!
Agregar la dynamicpalabra clave a la definición o una anulación parece darme el comportamiento deseado 'desde ese punto en la jerarquía de clases hacia abajo' ...
Cambiemos nuestro ejemplo a algo un poco menos construido, lo que realmente me hizo publicar esta pregunta:
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()
Ahora lo tenemos A B A. Aquí no puedo hacer que las subvistas de diseño de UIView sean dinámicas de ninguna manera.
Mover ambas anulaciones a su declaración de clase nos lleva de A A Anuevo, solo A o solo B todavía nos consigue A B A. dynamicDe nuevo resuelve mis problemas.
En teoría, podría agregar dynamica todo overridelo que hago, pero siento que estoy haciendo algo más aquí.
¿Es realmente incorrecto usar extensions para agrupar código como lo hago?