A chamada Delphi herdada em procedimentos substituídos se não houver chamada explícita
-
09-06-2019 - |
Pergunta
O Delphi chama herdado em procedimentos substituídos se não houver chamada explícita no código, ou seja, (herdado;), tenho a seguinte estrutura (de super para subclasse)
TForm >> TBaseForm >> TAnyOtherForm
Todos os formulários do projeto serão derivados do TBaseForm, pois este terá todas as configurações padrão e partes destrutivas que são utilizadas para cada formulário (segurança, validação etc.).
TBaseForm possui procedimentos onCreate e onDestroy com o código para fazer isso, mas se alguém (ou seja, eu) esquecesse de adicionar herdado ao onCreate em TAnyOtherForm o Delphi chamaria isso para mim?Encontrei referências na web que dizem que não é obrigatório, mas em nenhum lugar diz se será chamado se for omitido do código.
Além disso, se chamar herdado para mim, quando será chamado?
Solução
Não, se você deixar a chamada herdada, ela não será chamada.Caso contrário, não seria possível substituir um método e omitir totalmente a versão pai dele.
Outras dicas
Vale ressaltar que não chamar herdado no Destroy de nenhum objeto pode causar vazamentos de memória.Existem ferramentas disponíveis para verificar isso em seu código-fonte.
A chamada herdada deve ser feita explicitamente.Em geral, nenhuma linguagem chama automaticamente a função herdada em situações equivalentes (construtores de classe não incluídos).
É fácil esquecer de fazer a chamada herdada em um construtor de classe.Em tal situação, se uma classe base precisar inicializar quaisquer dados, você terá uma violação de acesso esperando para acontecer.
Talvez você possa substituir DoCreate e DoDestory em sua classe TBaseForm para garantir que algum código seja executado independentemente da implementação das classes filhas.
// interface
TBaseForm = Class(TForm)
...
Protected
Procedure DoCreate(Sender : TObject); Override;
End
// implementation
Procedure TBaseForm.DoCreate(Sender : TObject);
Begin
// do work here
// let parent call the OnCreate property
Inherited DoCreate(Sender);
End;
Herdado deve ser chamado explicitamente em objetos descendentes, bem como na herança de forma visual.Se você usar a conclusão de classe, ela será herdada automaticamente se você sinalizar a definição como substituição (mas não para reintrodução).Se você estiver usando herança de formulário visual, ao adicionar um novo manipulador de eventos por meio do editor de formulário, ele também adicionará o herdado.
O código herdado não é chamado implicitamente, como os outros indicaram.Você deve chamá-lo explicitamente.Isso lhe dá alguma flexibilidade útil.Por exemplo, você pode querer fazer algum código de pré-processamento antes do código herdado e, em seguida, fazer algum código de pós-processamento.Isso pode ser parecido com:
procedure TMyCalcObject.SolveForX;
begin
ResetCalcState;
inherited SolveForX;
PostProcessSolveForX;
end;
Não.Esse é o objetivo da substituição.
Você deve chamá-lo explicitamente.Isso permite muita flexibilidade, já que você pode escolher em qual ponto do código chamar o método herdado.Mas também é uma grande fonte de bugs.É fácil esquecer de chamar a função herdada e o compilador não tem como saber se você fez isso deliberadamente ou simplesmente esqueceu.
Deveria haver algum tipo de diretiva "skip_inherited" para informar ao compilador que você não deseja chamar o método herdado.
O compilador reportaria facilmente o erro se não encontrasse "herdado" ou "skip_inherited".Isso significaria que você esqueceu.Mas infelizmente ninguém no CodeGear pensou nisso.