Eu costumo colocar apenas as necessidades (propriedades armazenadas, inicializadores) nas definições de minha classe e mover todo o resto para elas próprias extension
, como um extension
bloco lógico que eu agruparia // MARK:
também.
Para uma subclasse UIView, por exemplo, eu terminaria com uma extensão para coisas relacionadas ao layout, uma para assinar e manipular eventos e assim por diante. Nessas extensões, inevitavelmente tenho que substituir alguns métodos do UIKit, por exemplo layoutSubviews
. Eu nunca notei nenhum problema com essa abordagem - até hoje.
Veja esta hierarquia de classes, por exemplo:
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()
A saída é A B C
. Isso faz pouco sentido para mim. Eu li sobre as Extensões de Protocolo sendo enviadas estaticamente, mas isso não é um protocolo. Esta é uma classe regular e espero que as chamadas de método sejam dinamicamente despachadas em tempo de execução. Claramente, a chamada C
deve ser pelo menos dinamicamente despachada e produzida C
?
Se eu remover a herança NSObject
e criar C
uma classe raiz, o compilador reclama dizendo declarations in extensions cannot override yet
, sobre o qual eu já li. Mas como ter NSObject
como classe raiz muda as coisas?
Mover as duas substituições para a declaração de classe produz A A A
como esperado, mover apenas B
produz A B B
, mover somente A
produz C B C
, o último dos quais não faz absolutamente nenhum sentido para mim: nem mesmo aquele digitado estaticamente para A
produzir mais a A
saída!
Adicionar a dynamic
palavra-chave à definição ou a uma substituição parece me fornecer o comportamento desejado 'a partir desse ponto na hierarquia de classes para baixo' ...
Vamos mudar nosso exemplo para algo um pouco menos construído, o que realmente me fez postar esta pergunta:
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()
Agora chegamos A B A
. Aqui não posso dinamizar o layoutSubviews do UIView por qualquer meio.
Mover as duas substituições para a declaração de classe nos leva A A A
novamente, apenas A ou B ainda nos recebem A B A
. dynamic
novamente resolve meus problemas.
Em teoria, eu poderia acrescentar dynamic
tudo override
o que faço, mas sinto que estou fazendo outra coisa errada aqui.
É realmente errado usar extension
s para agrupar código como eu?