Baixe o app para aproveitar ainda mais
Prévia do material em texto
Escola Politécnica da Universidade de São Paulo Laboratório de Programação Orientada a Objetos para Engenharia Elétrica Aula 4: Encapsulamento PCS 3111 Agenda 1. Princípios da modularização 2. Encapsulamento • Métodos e Atributos Públicos e Privados 3. Coesão 4. Acoplamento 5. Métodos Setters/Getters 6. Processo de Compilação e Ligação 7. Organização de Arquivos: extensões .cpp e .h 8. Primitivas de Compilação: include e ifndef © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Princípios da modularização © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Introdução ! Uma boa prática no desenvolvimento de software é quebrar a solução em módulos (discutido nas aulas anteriores); ! Um dos critérios (princípios) para modularização é a ocultação da informação. © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Ocultação de Informações ! Uma solução modular esconde detalhes do módulo de outros módulos ! Especifica um módulo do ponto de vista externo ! Separa o propósito de um módulo de sua implementação ! Restringe o acesso de outros módulos a detalhes de implementação e a qualquer estrutura de dados do módulo; ! Em desenvolvimento de software a ocultação de informações é definida como Encapsulamento. © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Encapsulamento © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Encapsulamento Encapsulamento em programação orientada a objetos é capacidade de ocultação de detalhes de implementação de uma classe por parte de outras classes que a manipulam. ! O encapsulamento esconde detalhes da classe que não essenciais para compreender suas características; ! O encapsulamento permite o acesso a membros privados da classe (atributos e métodos) de uma interface bem definida de acesso (métodos). © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Encapsulamento ! Encapsulamento em classes de objetos é implementado em C++ utilizando-se: Private e Public. Membros da Classe (Exemplo: atributos) Interface de acesso (Exemplo: métodos) © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Private e Public em C++ class X { // Classe de nome X public: // Membros Públicos – // interface para acesso externo // a Classe X. // Métodos e atributos. private: // Membros privados – // detalhes de implementação da Classe, // acessível somente pelos membros // dessa classe. // Métodos e atributos. }; © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo em C++ … 8 class Carro { 9 private: 10 string fabricante; 11 int quilometragem; 12 public: 13 string cor; 14 void iniciaCarro (string f, string c); 15 void exibeCarro(); 16 }; 17 18 void Carro::iniciaCarro (string f, string c) { 19 fabricante = f; 20 cor = c; 21 quilometragem = 0; 22 } 23 24 void Carro::exibeCarro() { 25 cout << "Dados do Carro: " << endl; 26 cout << "fabricante: " << fabricante << endl; 27 cout << "cor: " << cor << endl; 28 cout << "quilometragem: " << quilometragem << endl; 29 } EX01 © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Private e Public em C++ ! Membros de Classes são privados por default. Ex: class X { int mf(); // … }; ! Significa: class X { private: int mf(); // … }; ! Assim: X *x; // Variável x referencia um objeto da Classe X x = new X; int y = x->mf(); // erro: mf é private(inacessível fora // da classe X) EX02 © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Coesão © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Coesão ! Definição: é o grau em que as responsabilidades de um único componente formam uma unidade significativa. (Budd, 2005) ! Coesão avalia o quanto os membros (atributos e métodos) de uma classe estão relacionados entre si. ! Coesão é uma métrica que pode ser classificada como Alta (membros fortemente relacionados) ou Baixa (membros pouco relacionados). ! Coesão Alta é imprescindível em programação modular. ! Entende-se que uma classe tem Coesão Alta quando os membros de uma classe estão relacionados a um tema comum e tem o mesmo objetivo. © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de Coesão Alta . class Relogio { private: int hora; int minuto; int segundo; public: void iniciaRelogio (int h, int m, int s); void incrementaMinuto(); void exibeHora(); } ! Observe que todos os membros da Classe estão relacionados com Relógio. EX03 © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de Coesão Baixa class Relogio { private: int hora; int minuto; int segundo; bool acesa; public: void iniciaRelogio (int h, int m, int s); void incrementaMinuto(); void exibeHora(); void ligaLampada(); }; ! Observe que os membros acesa e ligaLampada não estão relacionados com o conceito de Relógio e sim com Lâmpada. EX04 © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de Coesão Baixa ! Observe que a classe Aluno inclui também o conceito de notas e cálculo de média. 7 class Aluno { 8 private: 9 string nome; 10 int p1, p2, p3; 11 12 public: 13 void setNome (string nome); 14 string getNome(); 15 void iniciaAvaliacao (int p1, int p2, int p3); 16 int calculaMedia(); 17 }; EX05 © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de Coesão Alta ! Observe que as classes Aluno e Avaliacao foram definidas separadamente. 7 class Avaliacao { 8 private: 9 int p1, p2, p3; 10 11 public: 12 void iniciaAvaliacao (int p1, int p2, int p3); 13 int calculaMedia(); 14 }; 15 16 class Aluno { 17 private: 18 string nome; 19 Avaliacao *avaliacao; 20 21 public: 22 void setNome (string nome); 23 string getNome(); 24 void setAvaliacao (Avaliacao *nota); 25 }; EX06 © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Acoplamento © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Acoplamento ! Definição: descreve a relação entre os componentes de software (Budd, 2005). ! Acoplamento avalia o inter-relacionamento entre as classes. ! Acoplamento é uma métrica e pode ser classificado como Alto/Forte (alta interdependência entre as classes) ou Baixo/ Fraco (baixa interdependência entre as classes). ! Classes que têm um Acoplamento Baixo são mais independentes entre si. O inverso vale para Acoplamento Alto. ! Como regra geral deve-se minimizar sempre que possível o acoplamento entre classes. © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de Acoplamento Observe os seguintes aspectos de acoplamento: ! A classe Lampada tem acesso direto ao atributo do objeto da classe Relogio; ! A classe Lampada utiliza diretamente um valor de atributo da classe Relogio para decidir se é noite. 17 class Lampada { 18 private: 19 bool acesa; 20 public: 21 void ligar(); 22 void desligar(); 23 void ligarNoite (Relogio *horaAtual); 24 }; 25 26 void Lampada::ligar() { 27 acesa = true; 28 } 29 30 void Lampada::desligar() { 31 acesa = false; 32 } 33 34 void Lampada::ligarNoite (Relogio *horaAtual) { 35 int hora; 36 hora = horaAtual->hora; 37 38 if (hora >= 18) acesa = true; 39 else acesa = false; 40 } EX07 © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de Acoplamento ! . 7 class Relogio { 8 private: 9 int hora, minuto,segundo; 10 public: 11 bool ehNoite(); 12 // outros metodos.. 13 }; 14 15 class Lampada { 16 private: 17 bool acesa; 18 public: 19 void ligar(); 20 void desligar(); 21 void ligarNoite (Relogio *horaAtual); 22 }; 23 24 bool Relogio::ehNoite() { 25 return hora >= 18; 26 } 27 28 void Lampada::ligarNoite (Relogio *horaAtual) { 29 if (horaAtual->ehNoite()) acesa = true; 30 else acesa = false; 31 } Solução para diminuir o Acoplamento da Classe Lampada: ! Remoção do código que acessa diretamente o atributo do objeto da classe Relogio. ! A classe Lampada não necessita conhecer quais valores específicos da hora que determinam se é noite. A definição de noite ficou restrita à classe Relogio. EX08 © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de Acoplamento 16 class Lampada { 17 private: 18 bool acesa; 19 public: 20 void ligar(); 21 void desligar(); 22 void ligarNoite (bool ehNoite); 23 bool isAcesa(); 24 }; ... 44 void Lampada::ligarNoite (bool ehNoite) { 45 acesa = ehNoite; 46 } … 52 int main () { 53 Lampada *l = new Lampada; 54 l->desligar(); 55 Relogio *r = new Relogio(); ... 58 l->ligarNoite(r->ehNoite()); ... 61 } Outra solução com acoplamento ainda menor: ! A classe Lampada não depende mais do Relogio (nem sabe que o Relogio existe) ! Alguém (o main no caso) é quem passa a informação para a Lampada EX09 © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de Acoplamento ! Existem várias possíveis soluções • Qual é a melhor? Receber o relógio ou um booleano? ! ...depende se é importante separar completamente Relógio de Lâmpada... • Projeto OO © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Métodos Setters/Getters © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Uso de métodos Setters/Getters ! Os métodos Mutators (setters) e Accessors (getters) são utilizados para alterar e acessar atributos declarados como privados. ! Os métodos setNome/getNome são utilizados para encapsular a manipulação direta dos atributos de uma classe. ! Esses métodos permitem esconder detalhes específicos de inicialização, validação e acesso aos atributos. ! Em C++ os métodos setNome/getNome podem ser utilizados para manipular os atributos declarados como privados. © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de uso de setNome/getNome class Quadrado { private: double lado; public: bool setLado (double l); double getLado(); }; bool Quadrado::setLado (double l) { if (l <= 0) return false else { lado = l; return true; } } double Quadrado::getLado() { return lado; } int main() { Quadrado *square = new Quadrado; square->setLado (6.0); cout << Quadrado de lado: " << square->getLado(); } ! Atributo local da classe declarado como privado. ! Métodos setLado/getLado para inicialização e acesso ao atributo lado. © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Exemplo de uso de setNome/getNome class Pessoa { private: string nome; int idade; public: void setNome (string nome); string getNome(); void setIdade (int idade); int getIdade(); }; void Pessoa::setNome (string n) { nome = n; } string Pessoa::getNome() { return nome; } void Pessoa::setIdade (int i) { idade = i; } int Pessoa::getIdade() { return idade; } ! Atributos locais da classe declarados como privados. ! Métodos setNome/getNome para inicialização e leitura de cada atributo. © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Processo de Compilação e Ligação © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Compilação e Ligação ! Código escrito em C++ (Código Fonte) – legível pelos humanos • Arquivos com extensões: .cpp ou .h (headers) ! O compilador traduz o Código Fonte em Código Objeto (também chamado de “Código de Máquina") • Arquivo com extensão .obj (Windows) ou .o (Unix); ! O ligador liga seu Código Objeto com outras bibliotecas de Códigos Objetos já existentes. Exemplos: bibliotecas de entrada/saída, código do Sistema Operacional, etc. • Arquivos com extensão: .obj (Windows) ou .o (Unix) e .lib; ! O resultado é um Programa Executável • Arquivo com extensão .exe (Windows) ou a.out em Unix. Compilador C++ Código Fonte C++ Código Objeto Ligador Programa Executável Biblioteca de Código Objeto © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Organização de Arquivos: extensões .cpp e .h © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Classes e Arquivos ! C++ permite definir e implementar mais de uma classe em um mesmo arquivo • Exemplo: sistema bancário class ContaCorrente {... }; int main (int argc, char** argv) {... } class Agencia {... }; void ContaCorrente::depositar (double valor) {... } void Agencia::adicionar (ContaCorrente c) {... } class Correntista {... }; bool ContaCorrente::retirar (double valor) { ... } © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Classes e Arquivos ! Como organizar as classes em um arquivo? ! Quantas classes devem ser colocadas em cada arquivo? ! Boa prática • Crie um arquivo separado para cada definição e implementação © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Definição ! Arquivo de cabeçalho: ".h" • Exemplo: ContaCorrente.h class ContaCorrente { private: double saldo = 0.0; public: void depositar (double valor); bool retirar (double valor); }; © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Implementação ! Arquivo .cpp • Necessário fazer um #include do ".h" • Exemplo: ContaCorrente.cpp #include "ContaCorrente.h" void ContaCorrente::depositar (double valor) { saldo += valor; } bool ContaCorrente::retirar (double valor) { if (saldo < valor) return false; saldo -= valor; return true; } Inclui a definição da Classe ContaCorrente © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Implementação ! Arquivo main.cpp ! Para compilar e ligar manualmente: #include <iostream> #include "ContaCorrente.h" using namespace std; int main() { ContaCorrente *conta = new ContaCorrente(); conta->depositar(1000); cout << conta->saldo << endl; } g++ -c -std=c++11 contacorrente.cpp -o contacorrente.o g++ -c -std=c++11 main.cpp -o main.o g++ contacorrente.o main.o -o main.exe © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Primitivas de Compilação: include e ifndef © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Diretivas de Compilação ! As Diretivas de Compilação utilizadas em C++ iniciam com o símbolo ‘#’, tais como: #include e #ifndef ! As Diretivas são utilizadas numa etapa inicial da compilação denominada pré-processamento. ! Nessa etapa as Diretivas de Compilação são processadas, incluindo ou removendo código fonte do arquivo compilado. © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Inclusão ! Indica para o compilador onde o arquivo a ser incluído está: • O arquivo pode estar em pastas diferentes; • Quando se inclui cabeçalhos da biblioteca padrão usa- se o "<" e ">" ! O compilador procura o arquivo onde as bibliotecas ficam ! Arquivos de cabeçalho também podem fazer inclusões • Exemplo: Agencia.h inclui a ContaCorrente.h #include <iostream> #include "ContaCorrente.h" Do projeto Da biblioteca padrão © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Diretiva ifndef ! Problema: múltipla inclusão de um cabeçalho • Exemplo: tanto a Agênciaquanto o Correntista incluem a ContaCorrente • Gera um erro de compilação! ! (Compiladores de outras linguagens evitam esse erro) ! Solução: diretiva #ifndef #ifndef CONTACORRENTE_H #define CONTACORRENTE_H class ContaCorrente { ... }; #endif Se CONTACORRENTE_H não estiver definido, define-o Fim do ifndef © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Classes e Arquivos ! Exemplo: arquivos de um sistema bancário • ContaCorrente.h e ContaCorrente.cpp • Agencia.h e Agencia.cpp • Correntista.h e Correntista.cpp • main.cpp © PCS / EP / USP 2016 – PCS 3111 – Aula 4 Bibliografia ! STROUSTRUP B. Princípios e práticas em programação com C++. Bookman. 2012. 1216p ! BUDD, T. An Introduction to Object-Oriented Programming. 3rd Edition. Addison-Wesley. 2001. ! Craig Larman, C. Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition) 3rd Edition., 2005 © PCS / EP / USP 2016 – PCS 3111 – Aula 4
Compartilhar