Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

lorena85

Classes e Métodos Final

Recommended Posts

Tudo bem pessoal

 

Queria saber o objetivo de Classes e Métodos declaradas como Final

 

1) Sei que Classes declaradas como Final é por que não pode ser estendidas e nunca será uma super classe (Qual o objetivo disso? Qual a intenção de impedir que uma classe possa ser estendida?)

 

2) Sei que Métodos declarados como Final é por que impede que classes filhas sobrecarreguem um método da classes pai (Qual o objetivo disso? Qual a intenção de impedir que um método possa ser sobrecarregado?)

 

Agradecerei muito que me ajudar, exemplos serão muito bem vindos :)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa pergunta, eu nunca tinha parado para pensar nisso, mas encontrei uma resposta razoável:

 

http://www.guj.com.br/java/57418-metodos-final

 

 

o fato de ser final é que o metodo é imutavel, por isso q ele nao eh herdado senao seria subscrito e seria mutavel, um exemplo disso é a class String ela é final..
espero ter ajudado se eu tiver errado alguem me corrige ae 283a16da79f3aa23fe1025c96295f04f.gif

Compartilhar este post


Link para o post
Compartilhar em outros sites

Primeiro deixa eu fazer um parêntese aqui que muito (se não tudo) do que rola lá no GUJ é sobre Java. Em PHP não temos uma classe String, por exemplo.

Final-izar uma classe (nossa, que horror), apesar de parecer estupidez é útil justamente para aquilo que ela propõe, classes que jamais podem ser uma superclasse.

Por exemplo, eu tenho um módulo responsável pelos cabeçalhos HTTP. Todas as classes derivam de AbstractField pois compartilham funcionalidades idênticas, porém cada cabeçalho HTTP tem um formato e regras específicos e precisariam ser validados. "Precisariam" porque não tem necessidade mesmo, eu é que exagerei na codificação quando elaborei isso :P

Enfim... Apesar de eu ainda não ter feito isso, eu poderia declarar cada cabeçalho como final porque são únicos, cada um tem um validador específico, implementado como concretização do método abstrato AbstractField::getValidator(), e um conjunto de opções próprios (uns aceitam mais de um valor, desses que aceitam múltiplos uns separam os valores por um caractere diferente e etc).

Não tem como cabeçalho B ser filho do cabeçalho A, porque B é B e A é A e ponto final. ;)

Outro exemplo é minha implementação inicial de tipagem primitiva. Quase todas as classes são finais, exceto Number é superclasse de Integer e Float, duas classes diferentes com regras diferentes.

Quanto a métodos declarados como final existem duas circunstâncias úteis para justificar usar: Funcionalidades muito específicas engatilhadas por algum método de uma superclasse cujo nome é genérico demais -E- Reflection.

No primeiro cenário, eu tenho como exemplo a implementação superficial de Traits (recurso do PHP 5.4+) para o PHP 5.3. Superficial pois, por hora, permite apenas herança múltipla a nível de métodos, não de propriedades. É um recurso bacana, mas eu parei de programar por um certo tempo ficou subdesenvolvido.

Enfim... O que interessa saber é que esse recurso é disparada através de Object::extend(), um método da minha super-superclasse (ela é classe-pai de quase todas) e, dado o nome bastante genérico, ele pode ser declarada como final para impedir que alguém sobrescreva e anulasse a funcionalidade

O segundo cenário, de Reflection, é porque a classe Reflection permite fazer uma espécie de Engenharia Reversa nas classes e nos métodos o que é particularmente útil para Aplicações que fazem uso de Annotations, fragmentos de informações escritos nos comentários das classes/métodos que são interpretados de alguma forma, por alguma rotina e fazem algo grande.

E no meu caso eu uso a keyword final nos métodos das classes de Controller que representarão uma action, isto é, serão executados quando uma determinada URI for recebida como Requisição.

Meu módulo de análise de roteamento, lê os comentários dos métodos das classes de Controllers em busca de fragmentos de informações para trabalhar. E como isso poderia gerar um overload em classes com muitos métodos eu restrinjo essa análise aos métodos públicos, através de ReflectionMethod::isPublic(), mas também finais, através de ReflectionMethod::isFinal().

Falei demais, espero que não tenha lhe confundido ainda mais. :grin:

Compartilhar este post


Link para o post
Compartilhar em outros sites
Obrigada pela explicação Bruno, mas ficou um pouco técnico para minha compreensão, eu sou apenas uma aprendiz ainda :graduated:
Poderia explicar numa maneira mais simples possível?! Mas mesmo assim, queria ressaltar algo:
Classe Final:

Não se pode ter uma especialização(sub classes) de uma classe declarada como final, pois seria uma bizarrice. Como você mesmo falou "não se tem como cabeçalho B ser filho do cabeçalho A, porque B é B e A é A e ponto final."

 

Método Final:

A implementação daquele método não pode sofrer nenhuma alteração, então por segurança colocamos a palavra chave Final nesse método, pois se esse método for subscrito numa determinada sub classe, poderá ocorrer futuramente bugs e erros no sistemas.

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

De forma simples:

 

Você usa [inline]final[/inline] para um método quando NÃO QUER que seu comportamento mude. Quando isso se aplica à classe toda, você usa essa keyword nela.

 

Como o Bruno já disse, são casos muito específicos onde não existe razão para estender uma classe ou sobrecarregar um método, pois seu funcionamento deve ser bem conhecido.

 

A regra é: pintou dúvida? Então NÃO use [inline]final[/inline].

Compartilhar este post


Link para o post
Compartilhar em outros sites

Orientação a Objetos não tem como um dos mais básicos objetivos representar o mundo real de forma programática? Um objeto Porta representa uma porta no mundo real, com suas características (proprieddes) e ações (métodos).

 

Declarar uma classe, que representa um objeto, como final é como dizer que aquele objeto não pode gerar subprodutos dele mesmo.

 

Por exemplo, imagine um objeto Porta e um objeto Portão. Ambos são basicamente a mesma coisa, tem características partilhadas, ações em comum, mas um Portão tem algumas coisas que uma Porta comum não tem (controle remoto, talvez).

 

Se você declarar a classe Porta como final, você está dizendo que não podem existir variações de uma Porta. Mas sabemos que um Portão é uma Porta, maior e com mais techie techie, mas ainda assim, na sua essência, uma Porta.

 

Agora imagine o mesmo para um Portão. O que poderia derivar de um Portão? Uma ponte levadiça medieval talvez, mas lembremos que classes filhas compartilham características e comportamentos da classe-pai e um Portão tem coisas que não tinham na época dos castelos.

 

Por isso declarar um Portão como final, é plausível, pois ele é um objeto final, Nada pode derivar dele. E se quiséssemos uma Ponte Levadiça, estenderíamos de Porta que é muito mais sensato.

 

Conceitualmente, o mesmo vale para os métodos, mas para os métodos a coisa não é assim tão evidente e eu prefiro deixar que os especialistas em O.C.P expliquem.

Compartilhar este post


Link para o post
Compartilhar em outros sites

:clap: :clap: :clap: :clap:

Bruno, explicação magnífica... rs (Sei que essa resposta não tem nada que ver com o tópico, mas precisava dar os parabéns)

Compartilhar este post


Link para o post
Compartilhar em outros sites

E olha que escrevi de noite, com muito sono e sem nenhuma cafeína.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vejo o termo FINAL, como uma segurança, para o caso de outras pessoas que venham a mexer no sistema, saibam que não se deve derivar nada dessa classe.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Orientação a Objetos não tem como um dos mais básicos objetivos representar o mundo real de forma programática? Um objeto Porta representa uma porta no mundo real, com suas características (proprieddes) e ações (métodos).

 

Não é de meu propósito criar uma discussão de cinco páginas, mas a resposta é não.

 

A orientação a objetos é um conceito bem abstrato e implementado de forma diferente em diferentes linguagens, apesar de algumas serem muito parecidas, como Java e C#. Não existe e, provavelmente, nunca existirá um conceito de como modelar o mundo real em linhas de código ou em qualquer outro tipo de arte, trabalho ou pensamento.

 

Cada linguagem se torna no final uma comunidade que resolve problemas e se comunica, cada uma pensando de uma forma distinta. Basta vermos como linguagens e comunidades radicalmente diferentes fazem certas coisas de modos não tão iguais. Compare Assembly, Java, Prolog e Haskell. Compare o ocidente com o oriente. Compare o latim com o árabe. Compare índios com europeus. A visão de mundo é diferente entre pessoas, comunidades e linguagens de programação. É errado afirmar que há conceito concreto de mundo real ou de algo natural.

 

Orientação a objetos é um dos meios de se construir abstração de software, não de se modelar o mundo real. Todo paradigma tem, em sua essência, sua forma de modelar algo. Linguagens procedurais fazem isso por meios de procedimentos, orientação a objetos faz isso por meio de troca de mensagens entre objetos, programação funcional faz isso por meio de funções transparentes referencialmente e assim vai.

 

Nós dizemos isso erroneamente porque passamos a considerar o que nós vemos no nosso cotidiano como o óbvio, natural, correto, significativo ou qualquer outra palavra que usemos. Você acha que a lâmpada era intuitiva para alguém além do Thomas Edison no início do século XIX? Você acha que uma tela sensível ao toque era algo natural nos anos 90? Você acha que a internet é algo que faz sentido para quem nasceu na década de 30? E por final, você acha que orientação a objetos é óbvio para quem pensa que é uma forma de modelar o mundo com linhas de código?

 

A propaganda destrói nosso pensamento a toda hora.

 

---

 

Falando exatamente da palavra-chave final, o PHP não é a melhor linguagem para ensiná-la. Java talvez seria uma excelente por tê-la em dois contextos diferentes: variáveis e propriedades, onde significa imutável e métodos e classes, onde significa "inerdável" (procura-se adjetivo, vivo ou morto).

 

No livro "Effective Java", o Joshua Block diz algo que, apesar de radical e divergível, faz sentido: para variáveis e propriedades, tornar final sempre que possível e para classes e métodos, tornar final sempre que não sejam programados para serem usados através de herança.

 

Na prática, final para classes e métodos é raríssimo de ser necessitado, já para variáveis e propriedades, na maioria das vezes é/deveria ser aplicado.

 

Às vezes final é uma arrogância lógica ao admitir que algo está tão especializado que não pode ser mais. Outras vezes é algo que não faz sentido e que só causa problemas (que atire a primeira pedra um desenvolvedor que usa/usou Java e quis herdar java.lang.String, mas não pôde). Outro caso é quando parte da equipe de desenvolvimento não entende o Princípio da Substituição e então os mais experientes dela acabam por tornar as classes finais para evitar desastres lógicos. Os 1% restantes dos casos são onde final faz um certo sentido lógico.

 

Especificamente falando da java.lang.String e dos wrappers de primitivos (java.lang.Integer, java.lang.Double, etc.), faz sentido aplicar final para o valor, já que uma instância deles é uma representação do valor (VO) e se não fosse imutável haveria a necessidade de clonar o valor para não ser modificado, o que infelizmente ocorre às vezes no PHP por ele ser mal feito (contra fatos não há argumentos, nada de flamewar pelo amor ao café). Já aplicar final para a classe em si é uma barreira porque impede a especialização deles, uma vez que uma classe Text poderia herdar de String.

 

Voltando ao PHP, onde há apenas final para classes e métodos, use apenas quando houver a necessidade, que certamente será pequena.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.