# Conceitos de Programação Orientada a Objetos (POO) ## Pilares da programação orientada a objetos ### 1) Abstração ![](https://i.imgur.com/b38g1xp.png) * Conceito relacionado à capacidade de obter apenas características relevantes de um contexto (uma conta de banco, um produto, uma pessoa etc.) para possibilitar a criação de uma Classe. * Na imagem acima, temos alguns casos de abstração, de modo que foram selecionados apenas aspectos importantes, naquele contexto, para compor determinada entidade. ### 2) Encapsulamento ![](https://i.imgur.com/wNGVyOX.png) * O encapsulamento é uma maneira de proteger o código, de modo que o acesso direto aos atributos de uma classe fica restringido. Também é possível criar restrições a determinados métodos. * É possível ter acesso aos atributos de uma classe encapsulada por meio dos métodos ***getters*** e ***setters***. * Não importa a forma utilizada para realizar um determinado procedimento, e sim se o resultado esperado de uma funcionalidade será entregue. * Torna um software mais flexível, pois facilita a manutenção e a criação de novas utilidades. --- ### 3) Herança ![](https://i.imgur.com/4l5U6Og.png) * A classe que está sendo gerada (**subclasse**) herda todos os atributos e métodos da classe geradora (**superclasse**). * Na imagem acima, quanto mais longe da classe Animal mais **especializada** é a classe e quanto mais próximo mais **genérica** é a classe. * Nesse pilar da POO é importante saber as palavras-chave ***abstract*** e ***final***. Esses conceitos podem ser aplicados para classes e métodos e ganharão os seguintes comportamentos: - **Classe abstrata**: não pode ser instanciada. Serve de "molde" para as subclasses. - **Método abstrato**: declarado, mas não implementado. Basta uma classe ter um método abstrato para ela também ser abstrata. Além disso, caso uma subclasse herde um método abstrato, é obrigatório sobrescrever (conceito muito utilizado em Polimorfismo, outro pilar da POO) esse método com uma implementação. - **Classe final**: não pode ser herdada. - **Método final**: não pode ser sobrescrito por uma subclasse. * Aqui também entra o termo ***protected***, um modificador de acesso que possibilita que apenas subclasses tenham acesso aos atributos de suas superclasses. Caso os atributos da superclasse fossem ***private***, nem as subclasses teriam acesso, sendo necessários os métodos *getters* e *setters*. * Por fim, não é possível que uma subclasse *extends* duas superclasses, ou seja, não é permitido a herança múltipla na implementação clássica do Java. No entanto, é possível que uma classe esteja vinculada a mais de uma interface. --- ### 4) Polimorfismo ![](https://i.imgur.com/DHzXkUR.png) * **Polimorfismo de sobreposição (*Override*)**: - Como citado no tópico método abstrato, caso uma subclasse estenda uma classe abstrata que possua métodos abstratos, é obrigatório que esses métodos abstratos sejam sobrescritos e implementados nessa subclasse. - No caso da imagem acima, a classe abstrata *Funcionário* possui um método abstrato *calculoSalario()* e as especializações PessoaFisica e PessoaJuridica possuem seus próprios métodos de *calculoSalario()* (métodos com a mesma assinatura, mas com comportamentos distintos), ou seja, o método abstrato da superclasse é sobrescrito e implementado de diferentes formas nas subclasses. - A associação (*upcasting*) do tipo específico (subclasse) com o tipo genérico (superclasse), por exemplo "Funcionario funcionario = *new* PessoaFisica("João", 35)", é feita em tempo de execução. --- ## Outros tópicos ### - Interface * Interface é um tipo que define um conjunto de operações que uma determinada classe deve implementar. * Na definição das interfaces há apenas a assinatura dos métodos, cabendo à classe que implementar essa interface definir o que for necessário. ![](https://i.imgur.com/AyRPiXh.png) ### - Inversão de controle / injeção de dependência * Inversão de controle: padrão de desenvolvimento que consiste em retirar da classe a responsabilidade de instanciar suas dependências. * Injeção de dependência: maneira de realizar a inversão de controle. Um componente externo faz a instância da dependência (interface) e, após isso, é injetada no objeto "pai". Pode ser implementada por meio de um construtor (implementação da interface/dependência entra como argumento do construtor), por exemplo. ![](https://i.imgur.com/8D9a9By.png) ![](https://i.imgur.com/x96uXKI.png) ![](https://i.imgur.com/YUrhcGF.png) * No caso acima, a classe *BrazilTaxService* implementa a interface *TaxService* e a instanciação dessa dependência é realizada fora da classe *RentalService*. Além disso, a injeção de dependência ocorre por meio do construtor da classe *RentalService*. * Dessa maneira, o código fica mais flexível, tendo em vista que a classe *RentalService* pode receber qualquer implementação da interface *TaxService*, como *GermanyTaxService*, *PortugalTaxService* etc.