A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Programação Orientada a Objetos

Apresentações semelhantes


Apresentação em tema: "Programação Orientada a Objetos"— Transcrição da apresentação:

1 Programação Orientada a Objetos
Interfaces e classes abstratas

2 Coesão e Acoplamento Interfaces Classes Abstratas
"Uma imagem vale mil palavras. Uma interface vale mil imagens.“ - Bem Schneiderman Coesão e Acoplamento Interfaces Classes Abstratas

3 Acoplamento e Coesão Coesão é o grau em que uma classe tem um único e bem focado propósito. Quanto maior a coesão, melhor é o projeto do sistema. {

4 Acoplamento e Coesão Acoplamento é o grau com que uma classe conhece a outra. Quanto menor o acoplamento, melhor é o projeto do sistema. Benefícios: modularidade, flexibilidade, manutenibilidade. Como minimizar dependências e maximizar o reuso? O acoplamento é uma medida de quão fortemente uma classe está conectada, possui conhecimento ou depende de outra classe Com fraco acoplamento, uma classe não é dependente de muitas outras classes Com uma classe possuindo forte acoplamento, temos os seguintes problemas: Mudanças em uma classe relacionada força mudanças locais à classe A classe é mais difícil de ser reusada, já que depende da presença de outras classes A classe GerenciadorDeNotaFiscal depende de 3 outras classe: DAO (Data access object), , serviço externo. Acoplar-se a uma classe significa depender dela. A classe GerenciadorDeNotaFiscal depende de DAO para acessar os dados e gerar a nota fiscal. Se DAO muda, existe uma grande possibilidade de GerenciadorDeNotaFiscal também mudar. E imagina só se tem outra classe que depende de GerenciadorDeNotaFiscal, as mudanças vão se propagando com muita facilidade, o que complica a manutenção do código. O mesmo aconteceria para as classes e Serviço Externo. Ou seja, quanto maior for a quantidade de classes dependentes maior a chance de uma delas mudar e impactar em mudança na classe principal.

5 Acoplamento e Coesão Acoplamento é o grau com que uma classe conhece a outra. Quanto menor o acoplamento, melhor é o projeto do sistema. Benefícios: modularidade, flexibilidade, manutenibilidade. A ideia então é reduzir o acoplamento entre nossas classes o máximo possível. Mas sabemos que é impossível desenvolver sistemas com zero acoplamento. Mas será que todo e qualquer acoplamento é realmente problemático? Por exemplo, a grande maioria dos sistemas em Java no mundo são acoplados com a interface List(afinal a necessidade de guardar conjuntos de elementos é presente na maioria das aplicações). E fazer uso dessa interface geralmente não é problema para os desenvolvedores. Esse é um acoplamento “que não ligamos muito”. A grande charada é entender a diferença entre o acoplamento com List e com o DAO, por exemplo. A diferença é que a interface List não muda! Se ela não muda, isso significa que ela não forçará mudanças na classe que a usa! Ou seja, apesar de estarmos acoplados, o problema é menor, já que ela nunca provocará mudanças em nossos códigos! Isso sem contar a quantidade de classes que a referenciam hoje. Se algum engenheiro da Sun alterar essa interface, ele terá um trabalho imenso para propagar a mudança em muitos pontos. Portanto, provavelmente ele não fará isso! Isso torna essa interface estável!

6 Acoplamento e Coesão Lembrar: prezar pela alta coesão e fraco acoplamento. Uma das maneiras de se conseguir fraco acoplamento é com interfaces. Coesão e acoplamento são conceitos interligados: classes coesas tendem a gerar baixo acoplamento. Classes ou interfaces estáveis são aquelas que não tendem a mudar. Acoplar com classes ou interfaces com essa característica é interessante, pois sabemos que a chance dela mudar é baixa. É por isso que interfaces são tão populares em códigos orientados a objeto. Interfaces tendem a ser estáveis, já que não possuem atributos ou implementação (coisas que tendem a mudar muito dentro de uma classe), e possuem muitas implementações embaixo dela (diminuindo a chance de algum programador mexer nela). Mais sobre em: e Livro certificado java e google.

7 Interfaces Imagine agora que no Banco, além do Gerente existe um Diretor, que também tem privilégios de acesso à operações restritas... Se lembram do nosso exemplo anterior? Suponha que agora tenhamos um Diretor que também tem acesso privilegiado, e deve autenticar-se para acessar o sistema. Como faremos para adicioná-lo ao nosso sistema?

8 Observem que agora nós temos 2 classes com mesmos métodos: Diretor e Gerente autenticam. Quem poderia me dizer um motivo pelo qual isso não é legal? Resp.: não poderíamos usar o polimorfismo aqui 

9 Interfaces Autentica não é um método de funcionário, e esse é o motivo pelo qual não poderíamos usar o polimorfismo.

10 Interfaces Uma alternativa seria utilizar 2 métodos login de maneira sobrecarregado, onde um receberia como argumento um Gerente e o outro um Diretor. Isso é legal? Resp.: Não! Por que? Imagine se futuramente precisarmos adicionar mais funcionários com capacidade de autenticação... Sempre que adicionarmos uma nova classe teremos que implementar um novo método. Desse modo, a classe SistemaInterno ficaria completamente acoplada, e a ocorrência de mudanças no projeto poderia acarretar mais mudanças nessa classe.

11 Interfaces Nós já aprendemos duas situações em que o polimorfismo pode ser aplicado. Quais são elas? Herança + sobrescrita Interface + implementação Polimorfismo só faz sentido quando há herança e sobrescrita de métodos, ou implementação de interfaces. O motivo é: para haver polimorfismo é preciso haver um método em uma superclasse e sua implementação ou sobrescrita em uma subclasse. Dito isto, sempre que possuirmos uma variável de referência da superclasse nós poderíamos “chamar” os métodos de instâncias das subclasses. Essa classe, inclusive poderia ser uma classe abstrata, cujo método autentica fosse abstrato, ou seja, deve ser implementado por quem herda. (Lembrar que classes abstratas não podem ser instanciadas!)

12 Interfaces E se nós precisássemos restringir o acesso dos nossos clientes ao sistema, de modo que eles possam acessar apenas através de senhas?

13 Interfaces

14 Interfaces O que precisamos para resolver nosso problema?
Interfaces! Por que? Nos permitirá referenciar Diretor, Gerente e Cliente de um mesmo modo, mas sem quebrar a semântica do nosso projeto. Quem implementa interfaces assina um contrato. Isto nos garante que toda a classe não abstrata que implementou aquela interface possua uma implementação concreta para todos os métodos da interface. Não contém implementações; Expõe o que a classe que assinou o contrato deve fazer, mas não como fazer; Dizemos herdou por herança ou herdou por interface Lemos a interface da seguinte maneira: "quem desejar ser autenticável precisa saber autenticar dado um inteiro e retornando um booleano". Ela é um contrato onde quem assina se responsabiliza por implementar esses métodos (cumprir o contrato).

15 { Interfaces O que precisamos para resolver nosso problema?
Relacionamento É-UM  também testamos com instanceof O que precisamos para resolver nosso problema? Interfaces! Por que? Nos permitirá referenciar Diretor, Gerente e Cliente de um mesmo modo, mas sem quebrar a semântica do nosso projeto. Quem implementa interfaces assina um contrato. Isto nos garante que toda a classe não abstrata que implementou aquela interface possua uma implementação concreta para todos os métodos da interface. Não contém implementações; Expõe o que a classe que assinou o contrato deve fazer, mas não como fazer; Quem assinar o contrato deve saber executar as seguintes operações com os seguintes argumentos e o seguinte retorno... contrato {

16 Interfaces Voltando ao nosso exemplo... Como resolver corretamente o caso de adicionar ao cliente a funcionalidade de autenticação?

17 ZOOM pra galera do fundão enxergar melhor 

18 Interfaces O implements pode ser lido assim: “A classe Gerente se compromete a ser tratada como Autenticavel, sendo obrigada a ter os métodos definidos neste contrato”.

19 Interfaces O implements pode ser lido assim: “A classe Diretor se compromete a ser tratada como Autenticavel, sendo obrigada a ter os métodos definidos neste contrato”. Como seria a implementação para cliente?

20 The right way of doing it!
Com isso, se nós programarmos para a interface Autenticavel nós ganhamos o poder do polimorfismo. Isso indica mais reuso e facilidade de manutenção.

21 Interfaces Polimorfismo com interfaces!

22 Interfaces O que vocês acharam dessa nossa implementação?
Na opinião de vocês, o sistema ficou com alto ou baixo acoplamento? Resp.: baixo acoplamento! Novas classes podem ser adicionadas com capacidade de autenticação, e sem necessidade de alterar a classe SistemaInterno, responsável pelo login.

23 Interfaces Regras Uma classe qualquer pode implementar várias interfaces; Uma interface qualquer pode estender uma ou várias interfaces; Com isso, a interface “adiciona” novos métodos ao seu contrato; Interfaces não contêm implementações concretas; Classes não-abstratas que implementam interfaces devem fornecer implementação para os métodos da interface Classes abstratas podem deixar de implementar um ou mais métodos da interface; Interfaces não são instanciáveis, mas suas subclasses as são (e assim brincamos com o polimorfismo).

24 Interfaces Dicas sobre interfaces:
Programe sempre pra uma superclasse!  Polimorfismo As interfaces são uma ótima maneira de manter baixo acoplamento no seu projeto. Identifique os comportamentos que são comuns e crie interfaces para eles, assim você poderá adicionar novas entidades sem precisar alterar muito código.

25 Interfaces Vamos lembrar um pouco de Geometria  (10 minutos)
Crie uma interface chamada AreaCalculavel. Agora crie algumas classes que devem implementar a interface AreaCalculavel: Quadrado, Retangulo e Circulo. Crie um Main para ver o polimorfismo em prática. Crie um array do tipo AreaCalculavel com um Quadrado, um Retangulo e um Circulo. Itere no array e calcule a área de cada um deles. Quadrado  double lado Retângulo  double largura, altura Círculo  double raio, utilizar Math.PI

26 Vamos recapitular o modelo do nosso sistema bancário.
Aqui nós utilizamos alguns conceitos interessantes relativos a OO: herança e interfaces. E o melhor de tudo, com eles pudemos utilizar todo o poder do polimorfismo. Qual dos 2 é o mais poderoso? Resp.: interfaces. Com a herança nós herdamos código, e isto aumenta o acoplamento do nosso projeto. Com interfaces nós herdamos “responsabilidades” – as implementações dos métodos. Isto não gera tanto acoplamento quanto um código concreto. Isto gera facilidade de manutenção porque as subclasses concretas da interface implementarão todos os métodos do contrato, e com isso nós podemos usar o polimorfismo a vontade. LEMBRE-SE: para isso, é importante que nós programemos para a superclasse (interface), assim podemos adicionar novas subclasses sem precisar mudar códigos de outras classes (isto é fraco acoplamento!). Dentro dessa comparação, vale a pena lembrar que só há polimorfismo com herança quando há sobrescrita, e nem sempre faz sentido sobrescrever determinado método da superclasse. (ex.: secretario não precisa reimplementar getBonificacao, a implementação que ele herda de Funcionario já é suficiente para ele). Ok, isto é uma revisão rápida das partes mais interessantes que aprendemos até agora.  Agora vamos ao real motivo de existir classes abstratas.

27 Classes Abstratas class ControleDeBonificacoes { private double totalDeBonificacoes = 0; public void registra(Funcionario funcionario) { this.totalDeBonificacoes += funcionario.getBonificacao(); } public double getTotalDeBonificacoes() { return this.totalDeBonificacoes; Se lembram da nossa classe ControleDeBonificacoes? Basicamente, utilizamos ela pra recuperar com mais facilidade a bonificação total que o banco está dando a seus funcionários. Onde está o polimorfismo nesta classe? Resp.: ao utilizarmos a referência Funcionário, poderíamos adicionar novas classes ao projeto sem precisarmos alterar a classe ControleDeBonificacoes. O método registra recebe qualquer referência do tipo Funcionario, isto é, podem ser objetos do tipo Funcionario e qualquer de seus subtipos: Gerente, Diretor e, eventualmente, alguma nova subclasse que venha ser escrita, sem prévio conhecimento do autor da ControleDeBonificacao. O que aconteceria se não existisse a classe Funcionario? Poderia haver polimorfismo? Não, né... E aí, precisaríamos sobrecarregar esse método para cada nova classe que implementássemos que fosse um “funcionario”. 1ª Pergunta: faz sentido termos uma referência do tipo Funcionario? Sim, sem ela não teríamos polimorfismo!

28 Classes Abstratas 2ª Pergunta: faz sentido criar uma instância de Funcionario? i.e., faz sentido dar um new em Funcionario? Outro caso: um modelo em que pessoa física e pessoa jurídica sejam subclasses de pessoa. É bem provável que pra esse sistema, só faça mais sentido criar instâncias de pessoa física ou jurídica. (já que é algo mais específico com informações mais importantes) A classe Pessoa é o ponto chave apenas para gerar o polimorfismo. Dar new em um Funcionario é algo que, na minha opinião, não faz muito sentido. Nós utilizamos a referência de Funcionario para usar o potencial do polimorfismo, mas, no fim das contas, o que queremos é que a referencia f aponte para um tipo/subclasse de funcionário, algo mais concreto como Gerente ou Secretario. Como resolvemos isto?

29 Classes Abstratas Dar new em um Funcionario é algo que, na minha opinião, não faz muito sentido. Nós utilizamos a referência de Funcionario para usar o potencial do polimorfismo, mas, no fim das contas, o que queremos é que a referencia f aponte para um tipo/subclasse de funcionário, algo mais concreto como Gerente ou Secretario. Como resolvemos isto?

30 Classes Abstratas O que significa abstrato, pra você?
Vocês concordam que a gente tem dificuldade de criar, ou dar forma, ou até explicar, tudo aquilo que é abstrato? Os engenheiros de software que criaram o Java também concorda, e é por isso que essa é a nossa primeira regra sobre classes abstratas: elas jamais podem ser instanciadas.

31 Classes Abstratas Regra nº 1:
Classes abstratas não podem ser instanciadas! O que significa abstrato, pra você? Vocês concordam que a gente tem dificuldade de criar, ou dar forma, ou até explicar, tudo aquilo que é abstrato? Os engenheiros de software que criaram o Java também concorda, e é por isso que essa é a nossa primeira regra sobre classes abstratas: elas jamais podem ser instanciadas.

32 Classes Abstratas class Gerente extends Funcionario{ //attrs
public double getBonificacao(){ return 0.2*this.salario; } E se nós fizermos a classe Gerente estender essa classe abstrata Funcionario... O que mudaria em relação ao caso em que a classe Funcionario não é abstrata? O que muda até o momento é só o fato da classe (abstrata) Funcionario não poder mais ser instanciada. Isso já é algo bem relevante pra a gente, uma vez que isso dá mais consistência ao projeto Fique claro que a nossa decisão de transformar Funcionario em uma classe abstrata dependeu do nosso domínio. Pode ser que, em um sistema com classes similares, faça sentido que uma classe análoga a Funcionario seja concreta no sistema.

33 Classes Abstratas Métodos abstratos abstract class Funcionario{
protected double salario; public double getBonificacao(){ return 0.1*salario; } //outros métodos e atributos... Se ainda não sabemos quem é esse funcionário, será que faz sentido o método getBonificação ser concreto e retornar 10% do salário? Bem, isso é uma decisão de implementação. Talvez fizesse sentido pelo fato da bonificação padrão ser 10% para a maioria dos funcionários.

34 Classes Abstratas Métodos abstratos abstract class Funcionario{
protected double salario; public abstract double getBonificacao(); //outros métodos e atributos... } Mas e se para o nosso sistema as bonificações fossem majoritariamente diferentes? Talvez fizesse um pouco mais de sentido que a gente forçasse todo novo tipo de funcionario a ser implementado especificar como seria sua própria bonificação. Faríamos isso adicionando a palavra-chave abstract ao método getBonificacao. Por que não colocar corpo algum no método? Porque esse método nunca vai ser chamado, sempre que alguém chamar o método getBonificacao, vai cair em uma das suas filhas, que realmente escreveram o método. Com isto, esse método não teria implementação na superclasse Funcionario e deveria ser implementado por toda nova subclasse (que não fosse abstract). Qualquer classe que estender a classe Funcionario será obrigada a reescrever este método, tornando-o "concreto". Se não reescreverem esse método, um erro de compilação ocorrerá.

35 Classes Abstratas ControleDeBonificacoes
public void registra(Funcionario f) { System.out.println("Adicionando bonificação do funcionario: " + f); this.totalDeBonificacoes += f.getBonificacao(); } Esse é nosso método que registra a bonificação de um funcionario na classe ControleDeBonificações. Mas como esse método é chamado se ele não tem corpo? Resp.: polimorfismo. Já que o método é abstrato, com certeza suas subclasses têm esse método, o que garante que essa invocação de método não vai falhar. Uma referência de Funcionario nunca apontará para um objeto Funcionario, ou para uma subclasse abstrata de Funcionario. Ele só apontará para uma instância de uma subclasse não abstrata de Funcionario, e isso garante a existência de uma implementação para esse método.

36 Classes Abstratas Suponham que Diretor é-um Gerente
Esqueçam aquela nossa ideia anterior que ambos eram funcionários mas Diretor não era subclasse de Gerente... Resp.: não há problema. O código compilaria sim. Nós não quebramos nenhuma ideia da classe abstrata. Presidente e Gerente são classes não abstratas (concretas) e por isso fornecem a implementação do getBonificacao(), que é abstrato em Funcionario. Diretor, por sua vez, herda tudo que houver em Gerente e em Funcionario. Há algum problema no nosso design? Isto compilaria?

37 Classes Abstratas Há algum problema no nosso design? Isto compilaria?
Resp.: não há problema. Sim, compilaria. A classe Secretaria é abstrata, e escolheu não implementar o método getBonificacao(). Ela está no seu direito, uma vez que ela é abstrata. Toda subclasse de Secretaria que não for abstrata deve implementar os métodos abstratos definidos na hierarquia de classes. Logo, as classes concretas SecretariaAgencia e SecretariaAdministrativa tiveram que fornecer uma implementação concreta para o método getBonificacao(). Há algum problema no nosso design? Isto compilaria?

38 Classes Abstratas Regras Classes abstratas não podem ser instanciadas;
As classes abstratas não são obrigadas a ter um método abstrato – podemos querer que ela seja abstrata apenas para que ela não possa ser instanciada; Classes abstratas podem ser herdadas por outras classes abstratas; Toda classe concreta (não abstrata) que herdar de uma classe abstrata deve fornecer uma implementação concreta para os métodos abstratos (caso existam).

39 Classes Abstratas Regras
Apesar de não podermos dar new em classes abstratas, todas elas também tem um construtor! abstract class Animal { Animal () { System.out.println("Animal"); } Resultado: Animal Cachorro A criação do objeto é feita executando os construtores das superclasses até à classe em questão sendo instanciada. Ordem: classe mais genérica  classe mais especializada. Neste caso: Object, Animal, Cachorro. class Cachorro extends Animal { Cachorro ( ) { System.out.println("Cachorro"); }

40 Classes Abstratas Praticando! Vamos lembrar novamente daquele exemplo do Zoológico. O que vocês colocaram na implementação de emitirSom()? Animal emitindo som? Beleza, todos eles emitem, mas isso é genérico/abstrato demais para fornecermos uma implementação concreta para emitirSom() em animal. Eu tenho certeza que o método de todo mundo deve ter ficado muito estranho. Pra esse tipo de situação, faria mais sentido que Animal fosse genérico e que toda subclasse dele fornecesse uma implementação concreta para emitirSom().

41 Classes Abstratas Praticando!
Todos os animais emitem sons? Utilize os conceitos que aprendemos nessas 3 aulas de revisão para construir um modelo bem projetado para o nosso problema. Nem todo Animal emite som. Isso foi uma premissa errada que nós assumimos anteriormente. Se deixarmos emiteSom como abstrato em animal, somos forçados a programar de forma que todos eles emitissem sons. Para resolver isso poderíamos criar uma interface. Faz sentido que nossa classe animal seja abstract, para não instanciarmos ela, mas o método emitirSom() poderia ir para uma interface “Falável ou Dizível” (as palavras soam estranho, em inglês seria algo como Speakable). E assim, todo animal que emitisse som implementaria essa interface, e nós não forçaríamos um caracol (por exemplo) a emitirSom.

42

43 Referências Essa aula utilizou os exemplos das apostilas caelum.


Carregar ppt "Programação Orientada a Objetos"

Apresentações semelhantes


Anúncios Google