Estou refatorando um site herdado do PHP OOP.
Estou tão tentado a começar a usar 'final' nas aulas para " make it explicit that the class is currently not extended by anything
". Isso pode economizar muito tempo se eu for para uma classe e me perguntar se posso renomear / excluir / modificar uma protected
propriedade ou método. Se eu realmente quero estender uma classe, basta remover a palavra-chave final para desbloqueá-la e estendê-la.
Ou seja, se eu for para uma turma que não tem turmas filhas, posso registrar esse conhecimento marcando a turma como final. Na próxima vez que eu chegar lá, não precisaria pesquisar novamente a base de código para ver se ela tem filhos. Economizando tempo durante refatorações.
Tudo parece uma idéia sensata para economizar tempo ... mas muitas vezes li que as aulas deveriam ser feitas apenas 'finais' em ocasiões raras / especiais.
Talvez estrague a criação do objeto Mock ou tenha outros efeitos colaterais nos quais não estou pensando.
o que estou perdendo?
fonte
Respostas:
Quem escreveu isso está errado. Use
final
liberalmente, não há nada de errado nisso. Ele documenta que uma classe não foi projetada com herança em mente, e isso geralmente é verdade para todas as classes por padrão: projetar uma classe que possa ser herdada de forma significativa requer mais do que apenas remover umfinal
especificador; é preciso muito cuidado.Portanto, usar
final
por padrão não é ruim. De fato, muitas pessoas propõem que esse seja o padrão, por exemplo, Jon Skeet .Isso é realmente uma ressalva, mas você sempre pode recorrer a interfaces se precisar zombar de suas classes. Certamente isso é superior a tornar todas as classes abertas à herança apenas com a finalidade de zombar.
fonte
final
desempenharia um papel muito maior.Se você deseja deixar uma nota para si mesmo de que uma classe não tem subclasses, faça-o de qualquer maneira e use um comentário, é para isso que servem. A palavra-chave "final" não é um comentário, e usar palavras-chave no idioma apenas para sinalizar algo para você (e somente você saberia o que isso significa) é uma má idéia.
fonte
final
conforme o esperado. Não há nada de errado nisso. E usar um recurso de idioma para impor uma restrição é sempre superior a usar um comentário.final
deve indicar "Nenhuma subclasse desta classe deve ser criada" (por razões legais ou algo assim), não "esta classe atualmente não tem filhos, por isso ainda estou seguro de mexer com seus membros protegidos". A intenção definal
é a própria antítese de "livremente editável", e umafinal
classe nem deveria ter nenhumprotected
membro!final
significa "essa classe não deve ser estendida [por enquanto]". Nada mais, nada menos. Se o PHP foi projetado com essa filosofia em mente é irrelevante: ele possui afinal
palavra - chave, afinal. Em segundo lugar, argumentar a partir do design do PHP está fadado ao fracasso, dado o modo como o patchworky e o PHP são mal projetados.Há um bom artigo sobre "Quando declarar aulas finais" . Algumas citações:
PS Agradecemos a @ocramius pela ótima leitura!
fonte
"final" para uma classe significa: Você quer uma subclasse? Vá em frente, exclua a subclasse "final" o quanto quiser, mas não reclame se não funcionar. Você esta por sua conta.
Quando uma classe pode ser subclassificada, é um comportamento em que outras pessoas confiam, devem ser descritas em termos abstratos que as subclasses obedecem. Os chamadores devem ser escritos para esperar alguma variabilidade. A documentação deve ser escrita com cuidado; você não pode dizer às pessoas "olhe o código-fonte" porque o código-fonte ainda não existe. Isso é todo esforço. Se eu não espero que uma classe seja subclassificada, é um esforço desnecessário. "final" diz claramente que esse esforço não foi feito e dá um aviso justo.
fonte
Uma coisa que você talvez não tenha pensado é o fato de QUALQUER mudança de classe significa que ela precisa passar por novos testes de controle de qualidade.
Não marque as coisas como finais, a menos que você realmente as queira.
fonte
final
(uma mudança), só preciso testá-la novamente?final
? Esta é a experiência em primeira mão?final
classe tem um caso de uso primário. Você tem classes polimórficas que não deseja estender porque uma subclasse pode quebrar o polimorfismo. Não use afinal
menos que você deva impedir a criação de subclasses. Fora isso, é inútil.Usar 'final' tira a liberdade de outras pessoas que desejam usar seu código.
Se o código que você escreve é apenas para você e nunca será divulgado ao público ou a um cliente, você poderá fazer com o seu código o que quiser, é claro. Caso contrário, você evita que outros desenvolvam seu código. Muitas vezes tive que trabalhar com uma API que seria fácil de estender para minhas necessidades, mas fui impedida por 'final'.
Além disso, geralmente existe um código que não deveria ser melhor criado
private
, masprotected
. Claro,private
significa "encapsulamento" e oculta coisas consideradas detalhes de implementação. Porém, como programador de API, eu também poderia documentar o fato de que o métodoxyz
é considerado um detalhe da implementação e, portanto, pode ser alterado / excluído na versão futura. Portanto, todo mundo que confiar nesse código, apesar do aviso, está fazendo isso por seu próprio risco. Mas ele pode realmente fazer isso e reutilizar o código (espero que já tenha sido testado) e chegar mais rapidamente com uma solução.Obviamente, se a implementação da API for de código aberto, basta remover o 'final' ou tornar os métodos 'protegidos', mas você alterou o código e precisa acompanhar suas alterações na forma de patches.
No entanto, se a implementação for de código fechado, você ficará para trás com a localização de uma solução alternativa ou, na pior das hipóteses, com a mudança para outra API com menos restrições em relação às possibilidades de customização / extensão.
Observe que eu não acho que 'final' ou 'private' sejam ruins, mas acho que eles são usados com muita frequência porque o programador não pensou em seu código em termos de reutilização e extensão de código.
fonte