Baixe o app para aproveitar ainda mais
Prévia do material em texto
Paradigmas de Programação Responsável pelo Conteúdo: Prof. Me. Roberto Luiz Garcia Vichinsky Revisão Textual: Prof.ª Esp. Kelciane da Rocha Campos Programação Orientada a Objetos Programação Orientada a Objetos • Estudar os elementos da P.O.O. e os ambientes de desenvolvimento que oferecem suporte a este paradigma. OBJETIVO DE APRENDIZADO • Conceitos sobre Programação Orientada a Objetos (P.O.O); • Programação Orientada a Objeto com Linguagem C++; • Roteiro para a Construção do Programa em DEVC++; • Adicionando Métodos às Classes com C++. UNIDADE Programação Orientada a Objetos Conceitos sobre Programação Orientada a Objetos (P.O.O) Programação Orientada a Objetos (POO) é um modelo de desenvolvimento de software em que os elementos ou unidades constituintes do sistema são considerados “objetos” que se relacionam entre si. Um paradigma de programação depende mais da forma com a qual o desenvolvedor aborda o problema do que da linguagem de programação adotada para a implemen- tação da solução. Quando utilizamos o paradigma da programação estruturada (PE), desenvolvemos o programa pensando primeiramente nas funcionalidades deseja- das, naquilo que o sistema deve realizar e de que forma ele deve se comportar. Por outro lado, quando utilizamos o paradigma orientado a objetos (POO), modelamos o sistema a partir de uma visão sobre o mundo real, pensando primeiramente nos elementos ou “objetos” que irão integrar o sistema. O paradigma PE preconiza que todo programa deve ser escrito como um pro- cesso sequencial baseado nas três estruturas fundamentais: sequência, decisão e repetição, representadas pelos fluxogramas mostrados na Figura 1. Figura 1 – Estruturas de controle Fonte: Acervo do Conteudista O paradigma POO, por sua vez, é um modelo que tenta aproximar o raciocínio aplicado na programação ao raciocínio humano, incorporando conceitos do mundo real para a modelagem dos elementos, chamados aqui de “objetos”, que serão trata- dos pelo software. Neste paradigma, não se aplica o conceito de algoritmos ou pro- cedimentos sequenciais, como acontece no PE, mas sim o conceito de procedimen- tos não organizados sequencialmente, que são executados de acordo com estímulos sobre os “objetos”. Para iniciarmos o estudo da Programação Orientada a Objetos, devemos primei- ramente conhecer os elementos fundamentais desse paradigma, sendo eles: classe, objeto, atributo, método, herança, polimorfismo e encapsulamento. Veja suas defi- nições a seguir. 8 9 Classe Uma “classe” é, na realidade, um molde, ou um gabarito, que nos permite criar objetos de uma determinada categoria, ou seja, objetos que têm atributos e compor- tamentos comuns. Por exemplo, em um sistema de vendas, podemos ter uma classe chamada “Clientes”, que possui como atributos (propriedades) os campos “Nome”, “Endereço” e “Telefone” e como comportamentos, as funções “Incluir”, “Alterar” e “Excluir”, conforme representação gráfica apresentada na Figura 2. Figura 2 – Representação gráfi ca da classe “Cliente” Fonte: Acervo do Conteudista Objeto Um “objeto” é um elemento criado a partir de uma classe. Considerando o exemplo da classe “Cliente” citado anteriormente, podemos criar a partir dela os objetos, por exemplo, “José” e “Maria”, conforme representação gráfica apresentada na Figura 3. Figura 3 – Representação gráfi ca dos objetos “José” e “Maria” Fonte: Acervo do Conteudista Atributos São as características ou as propriedades de um objeto modelado a partir de uma classe. No exemplo da classe “Cliente”, veja que todos os objetos modelados a partir dela têm as mesmas propriedades (atributos), sendo elas: “Nome”, “Endereço” e “Te- lefone”. Porém, esses atributos possuem valores diferentes para cada objeto. No caso do objeto “José”, o atributo “Endereço” tem como valor “R. Tiradentes, 45”, e o objeto “Maria” tem como valor “R. Taquaral, 251”. 9 UNIDADE Programação Orientada a Objetos Métodos São as funcionalidades ou os comportamentos de um objeto modelado a partir de uma classe. Considerando ainda o exemplo da classe “Cliente”, observe que os mé- todos nela modelados são: “Incluir”, “Alterar” e “Excluir”. Isso significa que os objetos criados a partir dessa classe possuem funções que lhes permitem serem incluídos, alterados ou excluídos do sistema. Herança Chamamos de “herança” o mecanismo que permite que uma determinada classe compartilhe atributos e métodos de outra classe. Vamos novamente tomar o exem- plo da classe “Cliente”, que agora chamaremos de superclasse. Imagine que preci- samos criar duas outras classes, uma para cliente pessoa física e outra para cliente pessoa jurídica, as quais chamaremos de subclasses “P.Física” e “P.Jurídica”. Essas duas novas subclasses poderão herdar todos os atributos e métodos da superclasse “Cliente”. Esse processo de herança elimina as eventuais redundâncias que pode- riam ocorrer caso as duas subclasses fossem modeladas individualmente. Veja no diagrama apresentado na Figura 4 que as subclasses “P.Física” e “P.Jurídica” terão os mesmos atributos e métodos da superclasse “Cliente”. Figura 4 – Representação gráfica do processo de “herança” Fonte: Acervo do Conteudista Polimorfismo Polimorfismo é a qualidade de uma entidade ser capaz de assumir diferentes formas. No nosso contexto, é o princípio pelo qual as subclasses derivadas de uma única su- perclasse são capazes de invocar os métodos, que, apesar de apresentarem a mesma assinatura (identificação), podem se comportar de maneira diferente para cada uma das subclasses. Por exemplo, na nossa subclasse “P.Física”, o método “Incluir”, que é herdado da superclasse “Cliente”, exige que seja informado o CPF do cliente no momento da sua inclusão no sistema, ao passo que na subclasse “P.Jurídica”, esse mesmo método exige que seja informado o CNPJ do cliente. 10 11 Encapsulamento Encapsulamento é a capacidade de uma entidade (classe ou objeto) ocultar os detalhes da implementação de seus métodos, deixando exposto somente aquilo que pode ser acessado publicamente. É uma forma de proteção dos objetos que confere maior segurança ao projeto. Programação Orientada a Objeto com Linguagem C++ A maioria das linguagens de programação atuais dá suporte ao paradigma orien- tado a objetos (POO), como, por exemplo, JAVA, C#, Python, C++, VB.NET, dentre outras. Apesar das diferenças em relação às regras sintáticas dessas linguagens, os conceitos do paradigma POO são os mesmos. Adotaremos aqui a linguagem C++ para demonstrar a aplicação desse paradigma na implementação de programas. Como IDE (Integrated Development Environment – Ambiente de Desenvolvimento Integrado) usaremos o DEVC++, que é um ambi- ente de programação e compilação livre (gratuito), sob a Licença Pública Geral GNU (GNU GPL). O DEVC++. Faça o download gratuito do DEVC++. Disponível em: https://bit.ly/2NgRITB Criando objetos com C++ Lembre-se de que um objeto nada mais é do que uma instância de uma determi- nada classe. Portanto, para a criação de um objeto, é preciso que se crie primeira- mente uma classe. Para ilustrar esse processo, vamos construir uma classe chamada “Circulo” (observe que não usamos acentuação para definir o nome da classe) com o propósito de criarmos objetos do tipo círculo no nosso programa. Esta classe deve ter como atributos os campos “raio”, “x” e “y”, que determinarão o tamanho (raio) e a coordenada cartesiana ( x, y) do ponto central do círculo. A Figura 5 mostra a representação gráfica dessa classe. Figura 5 – Representação gráfi ca da classe “Circulo” Fonte: Acervo do Conteudista 11 UNIDADE Programação Orientada a Objetos O programa em linguagem C++ deve ser iniciado com as diretivas de pré-proces- samento para a inclusão das bibliotecas que contêm as funções a serem usadas no programa. Dentro do paradigma orientado a objetos, essas bibliotecas de funções são tratadas como classes e as funções são tratadas como objetos dessas classes. No nosso caso, precisaremosincluir no programa uma classe chamada “iostream”, que contém os objetos que manipulam o fluxo de dados de entrada e saída. Portanto, a primeira linha do programa deve ser: #include <iostream> A próxima instrução do programa deve definir um namespace (espaço de nomes) para que os objetos da classe “iostream” possam ser acessados de uma forma mais prática e segura. A definição do namespace para o nosso propósito deve ser reali- zada por meio da seguinte instrução: using namespace std; Em seguida, devemos utilizar o comando “struct” para criar a estrutura de dados correspondente aos atributos da nossa classe “Circulo”. Iniciamos a estrutura com a palavra reservada “struct” seguida pelo nome da classe (Circulo) e da abertura de chave ({). Dentro da estrutura, que deve ser delimitada por chaves, informamos os campos (atributos) da mesma forma que se declaram as variáveis, ou seja, indicamos para cada um dos campos o qualificador de tipo (int, float, double, etc.) e o nome, não esquecendo de colocar ponto e vírgula no final de cada declaração. As linhas de instruções para esse processo são mostradas a seguir. struct Circulo { float raio; float x; float y; }; Observe que a estrutura deve ser finalizada com um ponto e vírgula. Imagine agora que o nosso programa deve criar dois objetos da classe “Circulo”, conforme representação gráfica mostrada na Figura 6. Figura 6 – Representação gráfica dos objetos da classe “Circulo” Veja que os objetos A e B possuem atributos iguais, oriundos da classe “Circulo”; no entanto, os valores desses atributos são diferentes. O raio do círculo A é 1, ao passo que o raio do círculo B é 2. O ponto central x,y do círculo A é 1,1 e o do círculo B é 5,8. 12 13 Para a criação desses dois objetos, devemos definir duas instâncias da classe “Circulo” dentro da estrutura principal do programa (main). As linhas de instruções a seguir ilustram esse processo. int main() { Circulo A; Circulo B; Observe que a criação dos objetos A e B assemelha-se à declaração de variáveis, sendo que aqui o qualificador de tipo é na realidade o nome da classe (Circulo). O próximo passo é atribuir os valores para os atributos dos objetos A e B. Isto é como atribuir valores a variáveis comuns, a diferença é que devemos escrever o nome do objeto seguido por um ponto (.) e em seguida o nome do atributo em questão. Por exemplo, para atribuir o valor 2 ao atributo “raio” do objeto B, basta escrevermos B.raio=2;. Sendo assim, as próximas linhas do nosso programa são estas apresentadas a seguir. A.raio=1; A.x=1; A.y=1; B.raio=2; B.x=5; B.y=8; Dando continuidade à programação, vamos agora escrever as instruções para que os valores dos atributos dos objetos A e B sejam apresentados na tela. Usare- mos para esse processo o objeto cout da classe “iostream”, que é equivalente à função printf da biblioteca stdio.h. Para usar o cout devemos obedecer à seguin- te sintaxe: cout << expr_1 << expr_2 << ... << expr_n; Os parâmetros expr_1, expr_2 e expr_n representam as expressões que serão apresentadas na saída padrão, que no nosso caso é a tela. Essas expressões podem ser: um dado (variável, constante ou atributo de um objeto), uma cadeia de caracte- res (string), uma expressão matemática ou uma constante interna. Usamos também os caracteres << (dois sinais de menor) antes de cada um dos parâmetros. Veja alguns exemplos: • cout << “Alo mundo!”; // Mostra na tela a string “Alo mundo!” • cout << “Peso:” << p; // Mostra a string “Peso:” e o valor da variável p • cout << “Fim” << endl; // Mostra a string “Fim” e pula para a próxima linha 13 UNIDADE Programação Orientada a Objetos Dessa forma, o nosso programa deve ser finalizado com as seguintes linhas: cout << “Círculo A:” << endl; cout << “Raio:” << A.raio; cout << “ X:” << A.x; cout << “ Y:” << A.y << endl; cout << “Círculo B:” << endl; cout << “Raio:” << B.raio; cout << “ X:” << B.x; cout << “ Y:” << B.y << endl; } É importante salientar que esse programa não tem nenhuma aplicação prática, ele só serviu para demonstrar a criação de objetos por meio da linguagem C++. Para a fixação dos conceitos até aqui abordados, é imprescindível que você digite o programa no ambiente DEVC++ e analise o seu funcionamento. Para facilitar o seu trabalho, apresentamos a seguir o programa completo e um roteiro para orientá-lo(a) na sua construção. #include <iostream> using namespace std; struct Circulo { float raio; float x; float y; }; int main() { Circulo A; Circulo B; A.raio=1; A.x=1; A.y=1; B.raio=2; B.x=5; 14 15 B.y=8; cout << “Círculo A:” << endl; cout << “Raio:” << A.raio; cout << “ X:” << A.x; cout << “ Y:” << A.y << endl; cout << “Círculo B:” << endl; cout << “Raio:” << B.raio; cout << “ X:” << B.x; cout << “ Y:” << B.y << endl; } Roteiro para a Construção do Programa em DEVC++ 1. Abra a IDE do DEVC++ e inicie um novo arquivo através do menu File/ New/Source File., conforme mostra a Figura 7. Figura 7 – Menu File/New/Source File do ambiente DEVC++ Fonte: Acervo do Conteudista 15 UNIDADE Programação Orientada a Objetos 2. Na área de edição do novo arquivo, digite o programa obedecendo à formatação e principalmente às regras sintáticas da linguagem C++, con- forme a Figura 8. Figura 8 – Programa editado no ambiente DEVC++ Fonte: Acervo do Conteudista 3. Acesse o menu File/Save para gravar o programa. Quando for dar um nome ao programa, evite o uso de espaços e textos grandes, prefira nomeá-lo usando poucas letras, porém, garantindo que sejam suficientes para identificá-lo. Para este programa, dê o nome “CIRCULOS.CPP” e certifique-se de que o campo “Tipo” esteja apontando para “C++ Source Files” (arquivos fonte C++), conforme a Figura 9. Figura 9 – Tela de gravação do programa no ambiente DEVC++ Fonte: Acervo do Conteudista 16 17 4. Execute o programa por meio do menu Execute/Compile & Run, conforme mostra a Figura 10. Este comando fará a compilação e a execução do programa. Caso algum erro de sintaxe seja encontrado durante o processo de compilação, o programa não será executado e uma mensagem de erro será apresentada na guia “Compiler” no rodapé da IDE. Figura 10 – Comando para executar o programa no ambiente DEVC++ Fonte: Acervo do Conteudista 5. Caso a compilação seja concluída com sucesso, você verá o resultado da execução do programa em uma janela do tipo “prompt de comando”, conforme mostra a Figura 11. Figura 11 – Janela de execução apresentada pelo programa Fonte: Acervo do Conteudista Você deve ter notado que as letras acentuadas foram substituídas por caracteres estranhos na janela de execução. Observe que a palavra “Círculo”, que usamos como string para ser exibida na tela por meio da instrução cout<<”Círculo A:” aparece na tela com a letra i acentuada substituída por um caractere diferente. Para resolver este problema de configuração, devemos incluir no programa a biblioteca “locale.h”, que contém os protótipos das funções para configurações regionais (usaremos essa biblioteca na configuração do ambiente para a língua portuguesa). Após a inclusão da biblioteca “locale.h”, usamos a função setlocale para configurar as características regionais do ambiente. A sintaxe dessa função é apresentada a seguir. setlocale(LC_ALL,”Portuguese”); 17 UNIDADE Programação Orientada a Objetos Com essa instrução estaremos configurando o ambiente para trabalhar com o LC português (Language Code – Código da Linguagem). Dessa forma, to- das as letras acentuadas enviadas como saídas para a tela de execução serão impres sas corretamente. Com a configuração sugerida, nosso programa assumirá o seguinte aspecto: #include <iostream> #include <locale.h> using namespace std; struct Circulo { float raio; float x; float y; }; int main() { setlocale(LC_ALL,”Portuguese”); Circulo A; Circulo B; A.raio=1;A.x=1; A.y=1; B.raio=2; B.x=5; B.y=8; cout << “Círculo A:” << endl; cout << “Raio:” << A.raio; cout << “ X:” << A.x; cout << “ Y:” << A.y << endl; cout << “Círculo B:” << endl; cout << “Raio:” << B.raio; cout << “ X:” << B.x; cout << “ Y:” << B.y << endl; } 18 19 E como resultado dessa configuração, teremos a tela de execução conforme apre- sentado na Figura 12. Figura 12 – Janela de execução após inclusão da biblioteca “locale.h” Fonte: Acervo do Conteudista Adicionando Métodos às Classes com C++ Vimos até aqui como criar uma classe agregando a ela apenas os seus atributos ou propriedades. Vamos ver agora quais são os procedimentos para acrescentarmos métodos ou funcionalidades a uma classe. Para essa abordagem, vamos imaginar que precisamos construir uma classe para representar polinômios de segundo grau. Essa classe, que chamaremos simplesmente de “polinomio” (sem acento) deve ter como atributos os seguintes dados: coeficientes a, b e c; delta; primeira raiz e segunda raiz; conforme representação gráfica apresentada na Figura 13. Figura 13 – Representação gráfi ca da classe “polinomio” Fonte: Acervo do Conteudista Precisamos agora agregar na classe “polinomio” um método para o recebimen- to dos valores dos coeficientes a, b e c. Chamaremos esse método de “rec_coef”. Necessitamos ainda de outro método para calcular e mostrar as raízes da função polinomial, o qual chamaremos de “raizes”. Dessa forma, teremos a nossa classe “polinomio” conforme a Figura 14. 19 UNIDADE Programação Orientada a Objetos Figura 14 – Representação gráfica da classe “polinomio” com seus métodos Fonte: Acervo do Conteudista O início do programa deve conter as diretivas de pré-processamento para a inclusão das bibliotecas “math.h” (necessária para que possamos usar a função de raiz quadrada – sqrt) e “locale.h” (usada para a configuração regional do ambiente), além da diretiva para a inclusão da classe “iostream” (necessária para que possamos usar os objetos cin e cout, os quais manipulam os fluxos de entradas pelo teclado e saídas para a tela, respectivamente). E assim teremos as seguintes linhas iniciais: #include <math.h> #include <locale.h> #include <iostream> using namespace std; Em seguida, devemos construir a classe “polinomio” por meio de um arranjo do tipo “struct”, definindo inicialmente os seus atributos: struct polinomio { float a,b,c; float delta,x1,x2; A codificação do primeiro método, que chamamos de “rec_coef”, deve ser feita dentro do arranjo “struct”, seguindo o formato usual de uma função, ou seja, de- vemos indicar o tipo de dado que esse método vai retornar (neste caso não haverá retorno, portanto o tipo deve ser void), em seguida informamos o seu nome e entre colchetes escrevemos as instruções que esse método deve realizar: void rec_coef() { cout<<”Coeficiente a: “;cin>>a; cout<<”Coeficiente b: “;cin>>b; cout<<”Coeficiente c: “;cin>>c; } 20 21 Observe que existem apenas três linhas de instruções dentro do método “rec_ coef”, cada uma delas invocando o objeto cout para escrever na tela a string que identifica o coeficiente (a, b ou c) e em seguida, invocando o objeto cin para receber pelo te- clado o valor do coeficiente em questão. Lembre-se de que o objeto cout equivale à função printf da biblioteca stdio.h, assim como o objeto cin equivale à função scanf da mesma biblioteca. Da mesma forma, a codificação do segundo método, que chamamos de “raizes”, deve ser feita dentro do arranjo “struct”. Este método terá a função de calcular o delta do polinômio, de acordo com a fórmula de Bhaskara, e se o delta for negativo o método deve informar na tela a expressão “Não existe raiz real”, caso contrário ele deve calcular as raízes e exibi-las na tela. O código adequado para esse método é apresentado a seguir. void raizes() { delta=(b*b)-(4*a*c); if(delta<0) { cout<<”Não existe raiz real”<<endl; }else{ x1=(-b+sqrt(delta))/(2*a); x2=(-b-sqrt(delta))/(2*a); cout<<”x1: “<<x1<<endl; cout<<”x2: “<<x2<<endl; } } Para finalizar a aplicação, precisamos construir o corpo principal do programa (main), onde devem ser realizados os seguintes procedimentos: • configurar o ambiente para operar com a língua portuguesa; • instanciar um objeto “p” da classe “polinomio”; • dentro de uma estrutura de repetição sem fim (laço eterno), invocar o método “rec_coef” do objeto “p” para recebimento pelo teclado dos valores dos coefi- cientes a, b e c; • ainda dentro do laço sem fim, invocar o método “raizes” do objeto “p” para calcular e exibir na tela as raízes do polinômio. O código para realizar tais procedimentos é apresentado a seguir. int main() { setlocale(LC_ALL,”Portuguese”); polinomio p; 21 UNIDADE Programação Orientada a Objetos while(1) { p.rec_coef(); p.raizes(); } } E assim concluímos a construção de um programa para calcular as raízes de um polinômio de segundo grau! Você deve ter percebido que este programa poderia ter sido resolvido facilmente dentro do paradigma da programação estruturada, porém o intuito da adoção do paradigma orientado a objeto foi demonstrar essa nova forma de abordagem. Observe que durante toda a modelagem do programa, o polinômio foi considerado um objeto, sobre o qual definimos primeiramente os atributos (ou estru- tura de dados) e posteriormente definimos os seus métodos (ou suas funções), que é justamente o que preconiza o paradigma orientado a objetos: primeiro definem-se as “coisas” para somente depois definir suas funcionalidades. Para fixar esses conceitos, é importante que você digite o programa no ambiente DEVC++ e analise o seu funcionamento. Para facilitar o seu trabalho, apresentamos a seguir o programa completo. #include <iostream> #include <locale.h> #include <math.h> using namespace std; struct polinomio { float a,b,c; float delta,x1,x2; void rec_coef() { cout<<”Coeficiente a: “;cin>>a; cout<<”Coeficiente b: “;cin>>b; cout<<”Coeficiente c: “;cin>>c; } void raizes() { delta=(b*b)-(4*a*c); if(delta<0) { cout<<”Não existe raiz real”<<endl; }else{ x1=(-b+sqrt(delta))/(2*a); x2=(-b-sqrt(delta))/(2*a); 22 23 cout<<”x1: “<<x1<<endl; cout<<”x2: “<<x2<<endl; } } }; int main() { setlocale(LC_ALL,”Portuguese”); polinomio p; while(1) { p.rec_coef(); p.raizes(); } } 23 UNIDADE Programação Orientada a Objetos Material Complementar Indicações para saber mais sobre os assuntos abordados nesta Unidade: Sites Learning C https://bit.ly/2Yoyjq9 Livros Lógica de programação: a construção de algoritmos e estruturas de dados FORBELLONE, A. L. V.; EBESPACHER, H. F. Lógica de programação: a construção de algoritmos e estruturas de dados. 3ª edição. São Paulo: Pearson, 2005. Treinamento em Linguagem C MIZRAHI, V. V. Treinamento em Linguagem C. 2ª ed. São Paulo: Pearson, 2008. Vídeos Programação Orientada a Objetos (POO) – Dicionário do Programador https://youtu.be/QY0Kdg83orY 24 25 Referências PRESSMAN, R. S. Engenharia de software: uma abordagem profissional. 8ª ed. Porto Alegre: AMGH, 2016. ( e-book) SEBESTA, R. W. Conceitos de linguagens de programação. 11ª edição. Porto Alegre: Bookman, 2018. SOFFNER, R. Algoritmos e programação em linguagem C. 1ª edição. São Paulo: Saraiva, 2013. ( e-book) 25
Compartilhar