Prévia do material em texto
PROGRAMAÇÃO ORIENTADA A OBJETOS • 1. Introdução à Programação Orientada a Objetos . . . . . . . . . . . .3 • 2. Encapsulamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 • 3. Polimorfismo e Sobrecarga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 • 4.Herança, conceito, aplicações e desenvolvimento . . . . . . . . 27 • 5. Programação Orientada a Objetos - Abstração . . . . . . . . . . . 34 • 6. Debug e tratamento de erros na orientação a objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 • Encerramento do E-book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Sumário UNIDADE DE APRENDIZAGEM INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETOS PROGRAMAÇÃO ORIENTADA A OBJETOS 1 4 Breve contextualização Neste capítulo, abordaremos uma breve introdução sobre Programação Orientada a Objetos, uma metodologia de desenvolvimento que utiliza objetos que se comunicam por meio de funções e procedimentos. Toda essa forma de programação é uma mudança muito grande da forma tradicional de programação que utiliza a abordagem procedural. Contudo, para a academia, indústria, comércio entre outras áreas, é o método mais utilizado para o desenvolvimento de aplicações computacionais, pois essa técnica permite aos desenvolvedores uma fácil manutenibilidade. Objetivos da Disciplina • Capacitar o aluno para o desenvolvimento de software orientado a objetos, utilizando técnicas de programação orientada a objetos, muito utilizado no meio comercial e acadêmico; • Propiciar ao aluno uma adaptação (transição) entre a programação estruturada e a programação orientada a objetos; • Projetar, implementar, testar e depurar programas orientados a objetos; • Apresentar uma visão geral dos recursos avançados da linguagem. Apresentação do E-book Com o constante avanço da tecnologia computacional, testemunhamos uma superação significativa das limitações que outrora afetavam a performance dos sistemas. A evolução notável em termos de capacidade de memória RAM, poder de processamento e até mesmo capacidades de processamento de vídeo abriu portas para inovações substanciais no campo da programação de computadores. Essas conquistas tecnológicas transcendem as barreiras tradicionais, proporcionando um desenvolvimento e aprimoramento de novas técnicas de programação. O objetivo desse progresso está na busca por soluções que não apenas acelerem o processo de desenvolvimento de aplicativos, mas também elevem a barra em termos de facilidade de manutenção. Como resultado, surge uma abordagem mais eficiente que se reflete não apenas na velocidade de entrega, mas também na robustez e adaptabilidade das aplicações desenvolvidas. 5 Para Início de Conversa Ao nos aventurarmos na Programação Orientada a Objetos (POO), é imperativo reconhecer que a sólida compreensão da lógica de programação constitui o requisito essencial de toda programação, fornece as bases para a construção de soluções computacionais eficientes. Se porventura houver desafios na assimilação da lógica, é fundamental compreender que a abordagem adotada na POO difere substancialmente das práticas associadas às versões estruturadas da programação. Neste ponto inicial, é válido tranquilizar aqueles que possam sentir-se inseguros diante de obstáculos lógicos, ressaltando que a transição para a POO implica uma mudança de paradigma que, com a prática adequada, torna-se acessível. A familiaridade com os princípios da lógica aliada ao engajamento ativo na assimilação dos conceitos fundamentais da POO são passos cruciais nessa jornada de aprendizado. Este é apenas o começo, e ao enfrentarmos os desafios iniciais com determinação, construiremos as bases sólidas para uma compreensão abrangente e eficaz da Programação Orientada a Objetos. Objetivos de Aprendizagem do Capítulo • Introdução ao conceito de orientação a objetos; • Semelhança e diferença entre programação estruturada e POO; • Por que utilizar a POO; • Relação entre objetos e classe. 6 e classes. Uma linguagem OO deve fornecer suporte para quatro características “chave”: tipos abstratos de dados, herança, encapsulamento e polimorfismo. Um modelo OO tem como entidade fundamental o “objeto”, que recebe e envia mensagens, executa processamentos e possui um estado local. 1. INTRODUÇÃO AO CONCEITO DE ORIENTAÇÃO A OBJETOS Embora as linguagens orientadas a objetos já existam desde a década de 1960, nos últimos anos vem ocorrendo um crescimento sem paralelo no uso e na aceitação de tecnologias de orientação a objetos por todo o setor de software. Embora tenham começado como algo secundário, sucessos de linguagens, como Java e C++, têm impulsionado as técnicas orientadas a objetos - OO para novos níveis de aceitação. A Simula 67 foi a primeira linguagem que trouxe o conceito de objeto. Mais tarde, com a Smalltalk 80, a ideia de objeto ganhou mais importância. Tudo nessa linguagem são objetos, e cada um deles é uma instância de uma classe, em uma tentativa de aproximar o paradigma de programação ao mundo real. A Smalltalk foi bastante influente, já que a partir dela foram criadas outras linguagens de Programação Orientada a Objetos. Após anos em desenvolvimento e amadurecimento nos meios acadêmicos, a Programação Orientada a Objetos (POO) amadureceu até o ponto em que os profissionais de programação são capazes de perceber as promessas que a técnica contém. O paradigma de orientação a objetos é um modelo de programação que utiliza os conceitos de objetos FONTE: ENVATO ELEMENTS 7 2. SEMELHANÇA E DIFERENÇA ENTRE PROGRAMAÇÃO ESTRUTURADA E POO Quando iniciamos as primeiras etapas da aprendizagem de programação, temos que ter noção de que o primeiro tipo de programação que aprendemos é a lógica estruturada ilustrada na Figura 1. Isso não é um problema, pois existem diversos tipos de programação que utilizam a mesma ideia lógica, uma delas é a Programação Orientada a Objetos, são tão próximas que podemos utilizar os métodos da programação estruturada na POO. [fluxograma] [pseudo-linguagem] Sequência() 1 Tarefa a 2 Tarefa b Contudo, para começarmos a entender o conceito de POO, precisamos compreender que a programação estruturada é uma forma de escrever o código fonte que possui uma execução em sequência, decisão e interação, formando um único bloco de execução. Esse tipo de paradigma foi muito utilizado pelas vantagens e práticas que oferecia naquele momento, mas foi lentamente substituído pela POO, pois as vantagens apresentadas eram maiores do que as desvantagens. TABELA 1 - CÓDIGO DE CÁLCULO DA ÁREA DO RETÂNGULO (À ESQUERDA, O CÁLCULO SEGUINDO A PROGRAMAÇÃO ESTRUTURADA, E À DIREITA, O CÓDIGO SEGUINDO A PROGRAMAÇÃO ORIENTADA A OBJETOS FIGURA 1 – CONSTRUÇÃO ESTRUTURADA: SEQUÊNCIA Tarefa a Tarefa b 8 3. POR QUE UTILIZAR A POO Os conceitos que pavimentaram o desenvolvimento de software orientados a objetos baseiam-se em comunicação, ou seja, envio e recebimento de mensagens entre os objetos. Podemos exemplificar essa comunicação como a língua que os seres humanos utilizam para comunicar-se entre si, seja no registro escrito ou falado, que constitui a ferramenta de nossa comunicação. É por isso que em programação chamamos de linguagem o modo como trocamos mensagens para conseguir executar as tarefas que desejamos entre o ser humano e o computador. No entanto, com o tempo, foi percebido que existiam lacunas que ocasionavam falhas na estrutura de códigos, como a dificuldade de identificar um erro lógico ou até mesmo sintático. Na Tabela 1, observamos que o código possui algumas semelhanças quando comparado à programação estruturada, como é o caso da função de cálculo intitulada “calcularArea”, em que permanece a mesmo forma de cálculo eaté mesmo a estrutura principal “int main()” permanece inalterada. Dessa forma, o que precisamos mudar é somente a forma como pensamos logicamente para construir a estrutura de código orientado a objeto. A lógica do cálculo não sofre alteração, mas pequenas alterações ocorrem, pois vemos o problema como um objeto, e não uma estrutura única e densa de código, ou seja, no lugar de criar uma única estrutura de código, criamos classes que representarão os objetos. FONTE: ENVATO ELEMENTS 9 4. RELAÇÃO ENTRE OBJETOS E CLASSE Existe uma relação intrínseca entre um objeto e sua respectiva classe, pois para existir um objeto é necessária a criação de uma classe (FÉLIX, 2016). Dessa forma, podemos resumir que objetos correspondem à extensão do mundo real que serão agrupados nas classes. Por exemplo, ao andar em uma rua, vemos três carros estacionados – Polo 2023, Peugeot 208 e Strada 2023 –, ao analisarmos a identificação de objetos, não importando o modelo de carro, dizemos que os carros são objetos da classe carro, ilustramos essa definição na Figura 2. A primeira linha ilustrada na Figura 2 corresponde à classe, enquanto as demais aos objetos da classe (DEITEL; DEITEL, 2016). Dessa forma, podemos caracterizar que objetos são necessariamente apenas coisas que existem no mundo real e são subdivididos em três tipos: Contudo, não somente a programação sofreu avanços, mas a forma como interpretamos os problemas para elaboração das soluções, e assim muitas outras linguagens foram desenvolvidas para essa finalidade, por exemplo, a UML utiliza das vantagens da orientação a objetos para o desenvolvimento de seus respectivos diagramas, como é o caso do diagrama de classe. Além disso, quanto à manutenibilidade do software orientado a objeto é mais simples e fácil de ser realizada do que na programação estruturada. Como o foco da POO é facilitar a manutenibilidade do sistema, também podemos, ao aprender essa forma de programar, facilitar o desenvolvimento. O que antes parecia complexo torna-se mais simples, mas isso não depende somente da linguagem, mas do entendimento e compreensão do desenvolvedor/analista que está criando a ferramenta computacional. E para cada objeto desenvolvido, características únicas tomam forma. FIGURA 2 – CLASSE “CARRO” Carro Polo 2023 Peugeot 208 Strada 2023 10 • Abstração – Na abstração, tentamos ao máximo retirar as entidades e objetos do mundo real, dessa forma, a programação orientada a objetos consegue simular com mais exatidão instâncias da realidade nos softwares. • Encapsulamento – No encapsulamento, tentamos ao máximo retirar as entidades e objetos do mundo real da forma mais literal possível e abstrair itens nos códigos. • Herança – Evita repetição de atributos e métodos. • Polimorfismo – Utilizamos para criar “exceções” das heranças de características recebidas de classe ancestrais. • Objetos tangíveis • Restaurante • Prato de frutos do mar • Cartão de débito • Incidente (evento ou ocorrência) • Receber o casal • Servir o prato • Fazer o pagamento • De interação (transação ou contrato) • Fazer o pedido • Pedir a conta É preciso considerar que não há um modelo fechado sobre objetos, pois isso varia conforme a modelagem, podendo haver uma enorme variedade de objetos e classes entre eles. No entanto, quando vemos a variedade desses objetos, percebemos que existe uma certa relação entre eles, em que podemos utilizar técnicas que já foram preestabelecidas pela literatura, são elas: FONTE: ENVATO ELEMENTS 11 Referências DEITEL, Paul; DEITEL, Harvey. Java: como programar. [S. l.]: Pearson, 2016. FÉLIX , Rafael. Programação orientada a objetos. 1ª. ed. [S. l.: s. n.], 2016. 176 p. Disponível em: https://plataforma.bvirtual.com. br/Acervo/Publicacao/128217 Considerações Finais Toda a parte lógica computacional também sofre avanços tecnológicos, assim como programávamos de forma estruturada, novos métodos de programação foram desenvolvidos para que novas demandas pudessem ser sanadas, isso ocorre para facilitar a forma como desenvolvemos, testamos e prestamos manutenção no software desenvolvido, pois quanto mais fácil o desenvolvimento, mais fácil deve ser a manutenibilidade. O que aprendemos neste capítulo foi que a programação orientada a objetos não é um simples ato de programar, mas possui toda uma metodologia de desenvolvimento, sendo a principal delas o ato da abstração, que ao ser aplicado devemos reduzir o objeto analisado em uma classe com variáveis e métodos, cada objeto desenvolvido se comunica com outros objetos por meio de mensagens. UNIDADE DE APRENDIZAGEM ENCAPSULAMENTO PROGRAMAÇÃO ORIENTADA A OBJETOS 2 13 Para Início de Conversa Por se tratar de uma forma de programação diferente da estrutura, alguns pilares precisam ser respeitados, pois a programação orientada a objetos baseia-se na possibilidade de crescimento modular e permite a criação de entidades independentes que interagem entre si de maneira organizada e eficiente. Nesse contexto, o encapsulamento emerge como um dos pilares fundamentais da orientação a objetos, proporcionando um nível de abstração que resguarda a implementação interna de uma classe. Ao encapsular dados e métodos, torna-se possível controlar o acesso externo, garantindo a integridade do objeto e facilitando a manutenção do código. Esse conceito promove uma camada de proteção, evitando o acesso direto a detalhes internos e promovendo uma maior flexibilidade na evolução do sistema. Além disso, o encapsulamento contribui para a criação de interfaces claras, facilitando a compreensão e utilização das classes. Essa abordagem oferece benefícios significativos no desenvolvimento de software, promovendo a reutilização de código, a redução de dependências e a melhoria da segurança e confiabilidade do sistema. Objetivos de Aprendizagem do Capítulo Aprender como fazer um encapsulamento de acordo com a literatura utilizando linguagem de programação C++ e Java para uma excelente compreensão. 14 1. INTRODUÇÃO AO ENCAPSULAMENTO Quando optamos pela Programação Orientada a Objetos, um dos destaques é a capacidade de desenvolver partes separadas da aplicação de modo independente e juntá-las posteriormente, formando assim um único software. O que obtemos com essa forma de programação é a garantia de mais flexibilidade e facilidade quando surgem modificações nos programas (FÉLIX, 2023). Quando o encapsulamento surgiu nos anos de 1940, os programadores da época perceberam uma repetição dentro da mesma instrução do programa, o que era frequente, Dessa forma, logo os programadores passaram a requisitar o modelo repetido por meio de um único nome em diversas partes do software (FÉLIX, 2023). O objetivo do encapsulamento é permitir que, ao ser implementado, um objeto seja alterado sem afetar todo o sistema, o que torna o código mais fácil de manter, permitindo uma facilidade na reutilização do código em outras classes. 2. PARA QUE SERVE O ENCAPSULAMENTO? Depois de entendermos teoricamente que o encapsulamento é um método que permite a criação de acesso mais seguro aos dados armazenados, garantimos que os modificadores de acesso sejam aplicados adequadamente nas classes, permitindo visibilidade externa, mas apenas dos métodos determinados, ou seja, o encapsulamento está intimamente ligado ao conceito de ocultamento da informação, conhecido como “Information hiding”. Imagine a seguinte história: em uma pequena cidade, vivia uma família em uma casa acolhedora. Tudo corria bem até que um dia algo estranho começou a acontecer. Pessoas desconhecidas, que não eram familiares nem amigos, começaram a entrar na casa sem permissão. Esses intrusos pegavam as coisas da família, mexiam em seus pertences e criavam uma verdadeira bagunça. Desesperados para encontrar uma solução, a famíliadecidiu tomar medidas drásticas. Resolveram instalar portas em cada entrada da casa, para controlar quem poderia entrar e quem deveria ficar do lado de fora. Com essa medida, a casa tornou-se mais segura e organizada, proporcionando à família a tranquilidade que tanto desejavam. 15 3. COMO O ENCAPSULAMENTO FUNCIONA? Toda linguagem de programação focada no desenvolvimento orientado a objetos possui palavras reservadas que podem ser utilizadas para gerenciar o acesso às informações. O encapsulamento funciona com os modificadores de acesso aplicados aos atributos e métodos do objeto. Os principais modificadores de acesso são: • Private – Os atributos ou métodos que utilizam esse modificador só podem ser acessados de dentro da própria classe em que foram declarados. • Protected – Os atributos e os métodos marcados por essa palavra reservada podem ser acessados dentro dela. • Public – Esse tipo de encapsulamento marca a possibilidade de utilizar os atributos e métodos por qualquer classe. Sempre que utilizamos o encapsulamento, temos que ter ideia de que podemos utilizá-lo em várias linguagens de programação. Em geral, a maioria das linguagens orientadas a objetos, como Java, C#, C++, Python, Ruby, JavaScript e Essa situação peculiar na pequena cidade fez com que as pessoas começassem a refletir sobre a importância das portas em suas vidas. Foi quando alguém fez uma analogia interessante: as portas agiam como o encapsulamento na programação orientada a objetos. Assim como as portas protegiam a casa, o encapsulamento protege o acesso desautorizado aos dados e funcionalidades de um objeto, garantindo a segurança e organização do sistema. FONTE: ENVATO ELEMENTS 16 PHP, tem mecanismos para encapsulamento, mesmo que as sintaxes e as nomenclaturas possam se diferenciar entre si. O encapsulamento observado na Tabela 1 exibe formas de como encapsulamos os atributos e métodos de acordo com suas respectivas linguagens. Observamos que existe uma certa diferença de como fazemos em Java e C++, mas ambos possuem o mesmo objetivo e finalidade. Para encapsular um dos atributos precisamos informar dentro da classe o tipo de acesso que desejamos realizar; no nosso caso, escolhemos o modificador “private”, mas como observamos, os atributos não podem ser acessados diretamente, porém, para que possamos acessar, utilizaremos os métodos de acesso “get’s and set’s”. O encapsulamento deve ser usado sempre que utilizarem a programação orientada a objetos, pois fornece muitos benefícios, são eles: proteção de dados, modificabilidade, reutilização de código, testabilidade e segurança na informação. A ferramenta é útil para proteger os dados de um objeto de acesso indevido ou modificação acidental, alterar os detalhes de implementação de um objeto sem afetar o restante do sistema e reutilizar um objeto em diferentes partes do sistema sem preocupação com os detalhes de implementação. Depois que utilizamos toda a estrutura de encapsulamento, devemos tentar acessar as informações; para que isso seja possível, criamos objetos vazios ou inicializados e TABELA 1 – ENCAPSULAMENTO DE ATRIBUTOS E MÉTODOS EM JAVA E C++ LINGUAGEM DE PROGRAMAÇÃO JAVA LINGUAGEM DE PROGRAMAÇÃO C++ 17 Esse mesmo construtor é utilizado para criação dos objetos vazios. Na FIGURA 2, temos a criação do objeto “Casa” de forma vazia, na linha 38. precisamos entender o que é o construtor. O construtor é um método que recebe o mesmo nome da classe, não se esqueça de que o arquivo salvo tem o mesmo nome da classe e único. No entanto, o método criado que recebe o mesmo nome de sua classe não possui retorno ou “void”, utilizado para fornecer valores iniciais para variáveis de instâncias definidas pela classe ou uma forma de inicialização de um objeto já formado, ou seja, um construtor inicializa um objeto. Além disso, mesmo que não declare explicitamente o construtor, todas as classes já possuem construtores, visto que o próprio JAVA já fornece construtores. Na Figura 1, na linha 6 até 8, a imagem à esquerda possui o construtor declarativo, a imagem à direita mostra o construtor não declarativo, mas existente dentro da classe ”Casa”. FIGURA 1 – CONSTRUTOR VAZIO FIGURA 2 – CRIAÇÃO DO OBJETO 18 Referências FÉLIX, Rafael (org.). Programação orientada a objetos. 1. ed. São Paulo, SP: Pearson, 2016. E-book. Disponível em: https:// plataforma.bvirtual.com.br. ENVATO. Disponível em: https://www.envato.com/ Considerações Finais Entendemos e aprendemos que o encapsulamento na Programação Orientada a Objetos (POO) desempenha um papel crucial na construção de sistemas eficientes, seguros e organizados, e é fundamental essa prática de ocultar a implementação interna de uma classe e permitir o acesso controlado aos seus membros, como atributos e métodos. Assim como uma casa protege sua privacidade por meio de portas e paredes, o encapsulamento protege a integridade e a consistência do código. Além disso, o encapsulamento contribui para a evolução do software, permitindo a modificação interna de uma classe sem afetar diretamente outras partes do sistema. Isso resulta em sistemas mais flexíveis, adaptáveis e menos propensos a erros. Em suma, o encapsulamento na POO é como a chave que tranca a porta de uma casa, garantindo que somente as operações permitidas tenham acesso aos recursos internos. Ao compreender e aplicar esse conceito, os programadores fortalecem a estrutura de seus códigos, promovendo uma programação mais segura, eficiente e sustentável. 19 UNIDADE DE APRENDIZAGEM POLIMORFISMO E SOBRECARGA PROGRAMAÇÃO ORIENTADA A OBJETOS 3 20 Para Início de Conversa O polimorfismo e a sobrecarga são dois pilares da Programação, conceitos fundamentais na programação orientada a objetos que desempenham papéis cruciais na criação do software, flexível e eficiente. Ao explorarmos esses conceitos, um objeto pode assumir diferentes formas, e a habilidade de uma classe e oferecer funcionalidades distintas tornam-se essenciais no design de software. O polimorfismo, em sua essência, permite que objetos de diferentes tipos sejam tratados de maneira uniforme, promovendo uma abstração poderosa na construção de sistemas complexos. Contudo, a sobrecarga oferece uma perspectiva fascinante, permitindo que métodos de uma mesma classe possuam assinaturas diferentes, adaptando-se às variadas necessidades do programador. Todavia, conversaremos e aprenderemos sobre o polimorfismo e a sobrecarga, desvendando suas aplicações práticas e, acima de tudo, como esses conceitos moldam a elegância e eficiência na programação orientada a objetos. Objetivos de Aprendizagem do Capítulo • Conceito e desenvolvimento do polimorfismo; • Conceito e desenvolvimento da sobrecarga. 21 1. POLIMORFISMO E SOBRECARGA O polimorfismo tem como significado tomar muitas formas a partir de um único código diferente, selecionado por algum mecanismo automático, ou seja, teremos um único nome com vários comportamentos. Quando falamos de polimorfismo, não é uma aplicação nova, no nosso cotidiano utilizamos na língua portuguesa o mesmo verbo para diversos significados. Podemos destacar alguns exemplos: 1. Um grupo de casais saíram para dançar, mas acabaram dançando porque não chegaram a tempo para entrar no lugar. 2. Chico cantou a noite em sua primeira apresentação e Francisco cantou uma garota durante o show. Contudo, ao aplicarmos as funcionalidades aos objetos como uma porta, por exemplo, podemos abrir uma porta, fechar uma porta, seja ela de um carro, geladeira, uma garagem, entre outros. Pois a palavra porta pode ser aplicada a diversos objetos do mundo real, cada objeto interpreta a porta de sua maneira. Porém, podemos apenas chamar um método para abrir ou fechar uma porta. Uma linguagem orientada a objetos suporta o polimorfismo, temos como exemploa linguagem de programação C++, Java, Scala, Rust, PHP, Python, entre outros. Cada classe a seguir será um arquivo diferente com respectivo nome, todos ilustrados na Figura 1, Figura 2, Figura 3 e Figura 4. FIGURA 1 – (OBJETO “OBJECTANIMAL.JAVA”) FIGURA 2 - POLIMORFISMO DO OBJETO PATO 22 2. TIPOS DE POLIMORFISMO Existem vários tipos de polimorfismo, entre eles temos a sobreposição, polimorfismo de inclusão, polimorfismo paramétrico e sobrecarga. O polimorfismo de inclusão usa a capacidade de substituição das heranças (ainda veremos esse assunto) de uma classe mãe por qualquer classe descendente, para permitir um comportamento polimórfico nos métodos que usam a classe mãe. Na Figura 5 observe que a classe “ControleUniversal” está relacionada com a classe “Controle”, pois possui um atributo do tipo ControleUniversal. Mas, como as classes “Televisao”, “CarroBrinquedo” e “BarcoBrinquedo” são descendentes de “ControleUniversal”, elas podem substituir a classe “Brinquedo” em qualquer método que a utilize. Nesse caso, isso foi feito explicitamente, através da passagem de um objeto da classe “Televisao” para o método construtor de ”ControleRemoto”. As figuras mostram o polimorfismo em prática, a forma como foi publicada utilizou-se da linguagem de programação Java, mas com pequenas alterações é possívl adaptar o código para outra linguagem como C#, Python, C++, entre outras. Ao olharmos no detalhe, percebemos que existe uma hierarquia que é formada pela classe base “ObjectAnimal”, no qual seus métodos foram redefinidos pelas subclasses filhas. A hierarquia forma relacionamentos com capacidade de substituição, entre os progenitores. FIGURA 3 - POLIMORFISMO DO OBJETO CACHORRO FIGURA 4 - CLASSE PRINCIPAL QUE CHAMA OS OBJETOS PATO E CACHORRO 23 A seguir, em Figura 6, Figura 7, Figura 8 e Figura 9, vemos a implementação do exemplo ilustrado na Figura 5 na linguagem de programação Java. FIGURA 5 - MODELO UML DO POLIMORFISMO DE INCLUSÃO FIGURA 6 - IMPLEMENTAÇÃO DO CONTROLE DO POLIMORFISMO DE INCLUSÃO FIGURA 7 - IMPLEMENTAÇÃO DO “CONTROLEUNIVERSAL” DO POLIMORFISMO DE INCLUSÃO 24 A sobrescrita também conhecida como “override” está relacionada com um tipo de polimorfismo, no qual podemos especializar métodos de uma classe como ilustrado na Figura 10 e ao ser herdada por outra classe, realizamos alteração nos métodos como ilustrado na Figura 11. FIGURA 8 - IMPLEMENTAÇÃO DA CLASSE “TELEVISAO” DO POLIMORFISMO DE INCLUSÃO FIGURA 10 - CLASSE “PESSOAS” COM O MÉTODO TOSTRING() IMPLEMENTADO PARA SOBRECARGA FIGURA 9 - IMPLEMENTAÇÃO DA CLASSE “PRINCIPAL” PARA O POLIMORFISMO DE INCLUSÃO 25 Com relação ao tipo de retorno, este pode ser um subtipo do tipo de retorno do método sobrecarga, sendo o mesmo que o polimorfismo paramétrico, por exemplo: se o método da classe retornar um ”Integer”, é permitido que o novo método retorne um “Double” ou qualquer outro “Wrapper”. No entanto, o oposto não é permitido, gerando um erro de compilação. Na FIGURA 10, temos um exemplo na prática do polimorfismo do tipo sobrecarga implementado em Java. FIGURA 11 - CLASSE DEPARTAMENTO QUE HERDA A CLASSE “PESSOAS” COM O MÉTODO TOSTRING() IMPLEMENTADO PARA SOBRECARGA FIGURA 12 - SOBRECARGA IMPLEMENTADO EM JAVA 26 Referências FÉLIX , Rafael. Programação orientada a objetos. 1. ed. [S. l.: s. n.], 2016. 176 p. Disponível em: https://plataforma.bvirtual.com. br/Acervo/Publicacao/128217 Considerações Finais Como vimos, o polimorfismo é um conceito fundamental na programação orientada a objetos, permitindo que objetos de diferentes classes sejam tratados de maneira uniforme. Essa capacidade de um objeto assumir várias formas simplifica o código, promovendo reutilização e flexibilidade, algo inexistente na forma tradicional de programar. Em linguagens como Java e C++, o polimorfismo pode ser alcançado por meio de métodos sobrescritos e interfaces. Ele contribui para um design mais modular e extensível, facilitando a manutenção do código. Ao utilizar polimorfismo, desenvolvedores podem escrever código mais genérico, facilitando a adaptação a mudanças nos requisitos. No entanto, é crucial compreender os princípios e boas práticas para aproveitar ao máximo os benefícios do polimorfismo e garantir um código eficiente e robusto. 27 UNIDADE DE APRENDIZAGEM HERANÇA, CONCEITO, APLICAÇÕES E DESENVOLVIMENTO PROGRAMAÇÃO ORIENTADA A OBJETOS 4 28 Para Início de Conversa Para o início da implementação dessa técnica, precisamos entender que a herança é um dos pilares da programação orientada a objetos (POO), um conceito fundamental que permite criar classes com base em classes existentes, compartilhando características e comportamentos. A classe pai ou classe mãe, também chamada de superclasse, fornece atributos e métodos que podem ser herdados por suas subclasses. Isso promove a reutilização de código e facilita a manutenção. As subclasses, por sua vez, podem estender ou modificar o comportamento da superclasse, adicionando novos atributos ou métodos. A herança cria uma hierarquia de classes, facilitando a organização e compreensão do código. Entender o princípio da herança é crucial para construir sistemas eficientes e flexíveis em POO. Objetivos de Aprendizagem do Capítulo • Conceito de herança na POO. • Implementação da herança em duas linguagens de programação diferentes. 29 1. CONCEITO DE HERANÇA No dicionário, identificamos que herança possui diversos significados: Ação de herdar; Aquilo que se herda ou que se deve herdar; O que se transmite com o sangue; Legado, domínio; entre eles. Quando voltamos à computação, todo esse significado é utilizado na prática nas implementações das classes. Ao utilizarmos a herança na POO, por meio de uma classe, utilizamos os métodos e funções já existentes na classe, herdada adquirindo os membros de uma classe existente e, possivelmente, aprimorando-os com capacidades novas ou modificadas. Com a herança, você economiza tempo durante o desenvolvimento de programas baseando novas classes existentes em software testado, depurado e de alta qualidade. Isso também aumenta a probabilidade de que um sistema seja implementado e mantido efetivamente. Dessa forma, ao criar uma classe, em vez de declarar tudo novamente, podemos designar que as novas classes herdem membros da classe existente, tipo de metodologia conhecido como superclasse. Dessa forma, uma subclasse pode tornar-se uma superclasse para futuras subclasses. 2. SUPERCLASSES E SUBCLASSES Um objeto criado pode ser um tipo genérico ou específico que possa pertencer a um objeto de outra classe. Por exemplo, uma classe “automotor” é um “Carro”, assim como “Caminhão” e “Moto”. Como cada objeto de subclasse é um objeto de uma superclasse, e uma superclasse pode ter muitas subclasses, o conjunto de objetos é representado por qualquer uma de suas subclasses. Por exemplo, a superclasse Carro representa todos os tipos de carros, e assim por diante. Observe que na Figura 1 existe um agrupamento hierárquico, estruturas na forma de árvores. Note que temos uma estrutura que a classe “Automotor” é uma superclasse das subclasses “Carro”, “Caminhão” e “Moto”, da mesma forma essas subclasses podem se tornar superclasses das subclasses “Van”, “Caminhonete” e “Triciclo”. Cada seta na hierarquia que representa um relacionamento é ‘um’. À medida que seguimos as setas para cima nessa hierarquia de classe, podemos declarar, por exemplo, que “um Carro é um Automotor” e “um Caminhão é um Automotor”, mas “uma Van é um membro de Carro”. 30 Na Figura 2, declaramos a criação de um objeto chamado Automotor, a linha 3 inicia a declaração da classe e indica que ela não estende de nenhuma outra classe, tornando ela uma superclasse. Essa classe, por ser superior, deve possuir todos os dados genéricos, que são encontrados em comumentre outros automotores, em seguida podemos especializar as outras classes derivadas, como no nosso exemplo ilustrado na Figura 3, temos a classe Carro, que herda as características da superclasse Automotor e especializamos ela para as características a serem preenchidas e existente em carro. FIGURA 1 – DIAGRAMA DE CLASSES UML DA HIERARQUIA DE HERANÇA PARA AUTOMOTOR FIGURA 2 – OBJETO SUPERCLASSE AUTOMOTOR 31 Observamos na Figura 3 que para utilizar uma superclasse utilizamos na linguagem de programação Java a palavra reservada “extends”, dessa forma, conseguimos fazer uma classe ter todas as características da superclasse “Automotor”. Contudo, dependendo da linguagem de programação, limitações podem existir, há dois tipos de herança, são elas simples e múltipla. A herança simples já vimos anteriormente, em que somente utilizamos uma superclasse para passar suas características para a classe herdeira. No entanto, a herança múltipla entre classes ocorre sempre que uma subclasse possui duas ou mais superclasses imediatas, ou seja, é “filha” de mais de uma classe, dependendo da linguagem utilizada, algumas restrições são impostas, por exemplo, na linguagem de programação Java não podemos ter uma herança múltipla direta de vários objetos, mas utilizamos interfaces que simulam objetos por meio de assinaturas, para que possamos simular a herança múltipla. Já na linguagem de programação C++, podemos utilizar objetos específicos na herança múltipla. Para que na linguagem de programação Java funcione a herança múltipla, utilizamos uma interface. A interface é um recurso pertencente à linguagem de programação Java, que algumas linguagens orientadas a objetos podem possuir, para que permita que um determinado grupo de classes tenha métodos ou propriedades em comum, mas os métodos FIGURA 3 – SUBCLASSE CARRO QUE HERDA AS CARACTERÍSTICAS DE AUTOMOTOR 32 podem ser implementados em cada classe de uma maneira diferente. Quando utilizamos a interface, temos que entender que só existem assinaturas de métodos e propriedades, cabendo à classe que a utilizará realizar a implementação das assinaturas. Ilustramos na Figura 4 e na Figura 5 a implementação das assinaturas em uma interface Java e cada uma possui três assinaturas, também conhecidas como métodos que serão utilizadas pelas classes que herdarem essas assinaturas. Na Figura 6, temos um exemplo de herança múltipla implementada na linguagem de programação Java. Observe que na linha 3 utilizamos o ‘implements’ para fazer a chamada de várias interfaces e suas respectivas assinaturas, isso só ocorre porque diferente da ‘extends’, podemos herdar múltiplas interfaces que simulam um objeto por assinatura. FIGURA 4 – INTERFACE ‘CLOCK’ FIGURA 5 – INTERFACE ‘CALENDAR’ FIGURA 6 – CLASSE COM MÚLTIPLAS HERANÇAS 33 Referências DEITEL, Paul; DEITEL, Harvey. Java: como programar. [S. l.]: Pearson, 2016. FÉLIX , Rafael. Programação orientada a objetos. 1ª. ed. [S. l.: s. n.], 2016. 176 p. Disponível em: https://plataforma.bvirtual.com. br/Acervo/Publicacao/128217 Considerações Finais Entendemos neste capítulo que a herança na Programação Orientada a Objetos (POO) permite a reutilização de código, estabelece uma hierarquia entre classes e promove o polimorfismo. Contudo, deve-se evitar acoplamento excessivo para manter a flexibilidade do código. Classes abstratas e interfaces são ferramentas que garantem contratos e consistência. A substituição de métodos em subclasses oferece personalização do comportamento. A herança múltipla, quando suportada, pode aumentar a complexidade e causar ambiguidades. Alternativas, como a composição, podem ser preferíveis em alguns casos. Compreender os princípios da herança é essencial para um design de software robusto. 34 UNIDADE DE APRENDIZAGEM PROGRAMAÇÃO ORIENTADA A OBJETOS - ABSTRAÇÃO PROGRAMAÇÃO ORIENTADA A OBJETOS 5 35 Para Início de Conversa: A abstração é um dos conceitos fundamentais da Programação Orientada a Objetos (POO) e desempenha um papel crucial no desenvolvimento de software moderno. Ela permite aos programadores modelar objetos do mundo real de forma simplificada, enfatizando apenas os aspectos relevantes para o problema em questão. Na POO, os objetos são as unidades básicas de construção, cada um representando uma entidade com características e comportamentos específicos. Ao utilizar a abstração, os desenvolvedores podem encapsular a complexidade de um sistema, expondo apenas as funcionalidades essenciais e ocultando os detalhes internos de implementação. Isso promove a modularidade, reutilização de código e facilita a manutenção e evolução do software ao longo do tempo. Neste capítulo, exploraremos em detalhes o conceito de abstração em POO, examinando como ela é implementada em Java. Discutiremos também as técnicas e práticas recomendadas para criar abstrações eficientes e flexíveis, que promovam a simplicidade, coesão e baixo acoplamento entre os componentes do sistema. Ao compreendermos a importância e aplicação da abstração, estaremos capacitados a projetar e desenvolver sistemas de software mais robustos, escaláveis e fáceis de manter. Objetivos de Aprendizagem do Capítulo • Entender a abstração; • Aplicar a abstração; • Diferenciar abstração e códigos estruturados. 36 1. INTRODUÇÃO A orientação a objetos é um método de programação desenvolvido para abstrair características de objetos reais, resolvendo muitos problemas encontrados na linguagem procedural. A abstração é um dos pilares essenciais da Programação Orientada a Objetos, que vai além da simples identificação de objetos e suas interações. Ela envolve a criação de modelos conceituais que capturam as características essenciais e comportamentos significativos de entidades do mundo real, enquanto descartam detalhes irrelevantes ou secundários para o contexto da aplicação em desenvolvimento. Em outras palavras, a abstração capacita os desenvolvedores a simplificar a complexidade, concentrando- se apenas nos aspectos fundamentais para o problema em questão. Ao fazer isso, não só facilita a compreensão e a manutenção do código, mas também promove a reutilização e a extensibilidade, permitindo que os sistemas evoluam de forma ágil e eficaz. A concepção de tipos de dados é uma característica fundamental presente na maioria das linguagens de programação convencionais. Ao declarar o tipo de uma variável, estamos estabelecendo o conjunto de valores que essa variável pode assumir e as operações que podem ser realizadas com ela. A definição de um tipo de dados deve incluir a especificação dos objetos que compõem esse tipo e as operações que podem ser aplicadas a esses objetos. Além disso, é viável estabelecer uma forma de representação para esses objetos. A abstração de dados é uma técnica empregada para introduzir um novo tipo de objeto que se mostra relevante no contexto do problema a ser resolvido. Ao utilizar um tipo abstrato de dados, os usuários focam exclusivamente no comportamento dos objetos desse tipo, expresso por meio de operações significativas para eles, sem a necessidade de compreender como esses objetos são representados internamente ou como as operações são executadas sobre eles (princípio do encapsulamento). Dessa forma, uma abstração de dados compreende um conjunto de valores e operações que definem integralmente o comportamento dos objetos. Essa propriedade é assegurada ao tornar as operações a única maneira de criar e manipular os objetos, garantindo que todas as ações que os objetos possam sofrer sejam contempladas por meio das operações disponíveis. Mais precisamente, um tipo abstrato de dados pode ser definido como um tipo de dados que satisfaz as seguintes condições: A representação e definição do tipo e as operações nos objetos do tipo são descritos em uma única unidadesintática (como em uma Unit, em Turbo Pascal); 37 2. APLICAR A ABSTRAÇÃO Nas metodologias de Programação Orientada a Objetos (POO), classes e métodos abstratos desempenham um papel crucial ao fornecer uma estrutura comum para entidades (classes) de um programa que compartilham certas características, mas se diferenciam em outras. Imagine a necessidade de criar várias classes que possuem algumas características e comportamentos em comum, mas que também apresentam particularidades exclusivas, impossibilitando a utilização de uma única classe abrangente. Em tais cenários, podemos conceber uma classe superior que sirva como um modelo para as demais, estabelecendo uma estrutura-base e podendo incluir métodos já implementados por padrão ou não. A representação (implementação) dos objetos do tipo é escondida das unidades de programa que utilizam o tipo; portanto, as únicas operações possíveis em tais objetos são aquelas que fazem parte da definição (interface) do tipo. A programação utilizando tipos abstratos de dados adota o princípio de encapsulamento, que promove o ocultamento e proteção da informação, tornando a manutenção mais viável e facilitando a evolução dos sistemas. Com o encapsulamento que aprendemos nesta disciplina e a estrutura de dados que representa os objetos e dos procedimentos que realizam operações sobre esses objetos, qualquer alteração na estrutura de dados provavelmente demandará modificações nos procedimentos associados. Contudo, o impacto dessas modificações é limitado às fronteiras da unidade sintática que descreve o tipo (a unidade, neste caso). Desde que a interface permaneça inalterada, as unidades de programa que fazem uso desse tipo não precisam ser modificadas. FIGURA 1 - ABSTRAÇÃO DE CARRO E PESSOA 38 Os métodos que são comuns a todas as classes filhas podem ser implementados diretamente na classe abstrata, garantindo que todas as subclasses herdem esse comportamento. Por outro lado, métodos que necessitam de implementações distintas nas classes filhas podem ser apenas declarados como uma assinatura na classe abstrata, sem um corpo definido. Isso permite que cada classe filha implemente esses métodos de acordo com suas necessidades específicas. Em Java, a declaração de classes e métodos abstratos é feita com a inserção da palavra reservada Class. Veja o exemplo da classe Pessoa: A classe “Pessoa” contém um conjunto de características em comum que diferem de um objeto do tipo carro: Nome, CPF e Filhos são atributos que todas as pessoas precisam ter. Temos também dois construtores para a classe, ou seja, os responsáveis por criar o objeto em memória, onde um inicializa o objeto carro e o outro, além da inicialização do objeto, define que o preenchimento dos parâmetros seja obrigatório nos atributos da classe. FIGURA 2 - CLASSE PESSOA IMPLEMENTADO EM JAVA 39 na organização do código, tornando-o mais legível e fácil de manter. Por exemplo, em linguagens como C ou Pascal, os programas são geralmente estruturados em blocos de código que representam sequências lógicas de operações. 3. DIFERENCIAR ENTRE ABSTRAÇÃO E CÓDIGOS ESTRUTURADOS Abstração e códigos estruturados são conceitos fundamentais na programação, cada um com sua própria abordagem e benefícios distintos. A abstração na programação refere-se à capacidade de simplificar a complexidade de um sistema, concentrando-se nos aspectos essenciais e ignorando os detalhes irrelevantes. Ao criar abstrações, os desenvolvedores podem modelar entidades do mundo real de forma mais clara e concisa, facilitando a compreensão e a manutenção do código. Por exemplo, ao criar uma classe em programação orientada a objetos, estamos abstraindo um conjunto de propriedades e comportamentos que são relevantes para um determinado tipo de objeto, enquanto ocultamos os detalhes de implementação interna. Por outro lado, os códigos estruturados referem-se a um estilo de programação em que o código é organizado de forma linear e hierárquica, utilizando estruturas de controle como sequências, seleções e iterações. Nesse paradigma, o programa é dividido em pequenas unidades de código chamadas de procedimentos ou funções, que são projetadas para realizar tarefas específicas. A ênfase está na clareza e 40 Referências DEITEL, P. J.; DEITEL, H. M. Java: como programar. 10. ed. São Paulo, SP: Pearson, 2017. E-book. Disponível em: https:// plataforma.bvirtual.com.br/Acervo/Publicacao/39590. KÖLLING, M.; BARNES, D. J. Programação orientada a objetos com Java: uma introdução prática usando o Bluej. 1. ed. São Paulo, SP: Pearson, 2004. E-book. Disponível em: https:// plataforma.bvirtual.com.br/Acervo/Publicacao/310 RANGEL, Pablo; CARVALHO JUNIOR, José Gomes de. Sistemas orientados a objetos: teoria e prática com UML e Java. Rio de Janeiro: Brasport, 2021. E-book. Disponível em: https:// plataforma.bvirtual.com.br/Acervo/Publicacao/197367 Considerações Finais A abstração na Programação Orientada a Objetos (POO) é essencial para simplificar a complexidade dos sistemas, concentrando-se nos aspectos fundamentais e descartando detalhes irrelevantes. Ao criar modelos conceituais que representam entidades do mundo real, promove-se a compreensão, manutenção e evolução do código de forma ágil e eficaz. Por meio do encapsulamento, ocultam-se os detalhes internos dos objetos, promovendo a proteção da informação e facilitando a reutilização do código. Os tipos abstratos de dados permitem criar uma estrutura comum para entidades do programa, promovendo a modularidade e a extensibilidade do software. Ao aplicar a abstração de forma consciente e estratégica, os desenvolvedores estão preparados para enfrentar os desafios da programação orientada a objetos com confiança e eficiência. 41 UNIDADE DE APRENDIZAGEM DEBUG E TRATAMENTO DE ERROS NA ORIENTAÇÃO A OBJETOS PROGRAMAÇÃO ORIENTADA A OBJETOS 6 42 Para Início de Conversa: Debugging e tratamento de erros desempenham papéis importantes no desenvolvimento de software orientado a objetos, pois estamos lidando com entidades complexas e interconectadas, como objetos e classes, o que aumenta a complexidade do código e a probabilidade de erros. Dessa forma, necessitamos de algumas técnicas como o debugging, que utilizamos para identificar, isolar e corrigir defeitos ou bugs em um programa. Na orientação a objetos, isso pode envolver rastrear o estado e o comportamento dos objetos, verificar a hierarquia de herança, entender as relações entre classes e identificar onde e por que o código não está se comportando como esperado. Ferramentas de depuração, como breakpoints, inspeção de variáveis e rastreamento de pilha, são essenciais para o processo de debugging na orientação a objetos. Contudo, erros são evitáveis visualmente enquanto programamos, por exemplo, nenhum número pode ser dividido por zero, ou seja, podemos utilizar um tratamento para evitar esse erro, esses tratamentos de erros referem-se à maneira como lidamos com exceções ou situações inesperadas que podem ocorrer durante a execução de um programa. Objetivos de Aprendizagem do Capítulo • Compreender os princípios do debugging em um ambiente orientado a objetos. • Aplicar estratégias eficazes de debugging em código orientado a objetos; • Entender os conceitos de tratamento de erros. • Aplicar estratégias de tratamento de erros. 43 1. INTRODUÇÃO AO DEBUGGING EM PROGRAMAÇÃO ORIENTADA A OBJETOS Debugging, também conhecido como depuração, é o processo de identificar erros na construção dos algoritmos de computador. Na POO, o código é organizado em objetos e esses objetos interagem entre si por meio de mensagens, tais processos de depuração podem ser um pouco desafiador, mas é fundamental identificar erros para garantir que o software funcione conforme o esperado. Contudo, por se tratar da orientaçãoa objetos, existe uma certa complexidade, pois tudo é objeto e por objetos conversarem entre si, complicando, assim, um pouco o rastreamento da execução do programa. Mas todo o rastreamento é possível ser realizado em toda a estrutura do código e até mesmo no núcleo da linguagem, isso só mostra a eficiência de um excelente depurador. Além disso, podemos inserir durante a construção do código mensagens que informem como está a execução do projeto em tempo de execução. No mais, temos os testes unitários e os modelos de desenvolvimento como o TDD, que, na prática, ajudam a identificar e corrigir problemas de código desde o início do processo de desenvolvimento, fornecendo uma forma sistemática de verificar o comportamento esperado dos objetos em diferentes cenários. Além disso, um dos primeiros passos que aprendemos quando estamos aprendendo a programar é o teste de mesa ilustrado na Figura 1, fundamentado na Lógica de Programação, permitindo visualizar a execução de um programa, muitas vezes vinculado a um algoritmo para resolver problemas por meio de computadores. É uma etapa desafiadora para os novatos, frequentemente ignorada pelos programadores experientes, porém um dos princípios mais cruciais para aqueles que desejam desenvolver soluções codificadas para diversos problemas. No entanto, os depuradores seguem a mesma lógica do teste de mesa. FIGURA 1 - TESTE DE MESA FONTE: CARMONA (2013) 44 enquanto as linhas 9 até 13 adicionam as informações do carro. Por último, temos a linha 15, que imprime na tela o conteúdo do carro. Em seguida, vamos utilizar pontos de interrupção e vários comandos de depurador para examinar o valor de cada variável. 1. Abrindo o terminal de comando: “PowerShell”; 2. Compilando o aplicativo para depuração: para que isso seja feito, o depurador Java só funciona com os arquivos .class compilados com a opção de compilador ‘-g’, que gera informações utilizadas pelo depurador para ajudar a depurar os aplicativos. 2. FERRAMENTAS DE DEBUGGING PARA PROGRAMAÇÃO ORIENTADA A OBJETOS Uma comparação com os objetos criados é o LEGO. Construímos as coisas com peças de LEGO e criamos objetos que trabalham juntos para fazer a construção de um sistema. Mas como em qualquer projeto, às vezes as coisas não funcionam como o esperado, o mesmo ocorre na POO. Dessa forma, como um detetive, por meio de auxílios de depuradores (debugging), precisamos encontrar e consertar os problemas que surgem durante o desenvolvimento de software orientado a objetos (Deitel, 2017). O debugging, ou depurador automático, investiga o código por meio dos pontos de interrupção, tais pontos marcam qualquer linha executável do código, para que a execução do aplicativo alcance o ponto de interrupção informado, a execução do código pausa por um tempo, permitindo que sejam examinados os valores das variáveis para ajudar a determinar se há erros de lógica. O código ilustrado na Figura 2 apresenta o cadastro de um carro em um sistema orientado a objetos. Na linha 5, temos a declaração da classe “Main”, a linha 7 mostra o método de execução, a linha 8 cria um objeto e inicializa de forma vazia, FIGURA 2 – PRINCIPAL DO OBJETO CARRO FONTE: O AUTOR 45 3. Iniciando o depurador (debugging): no “PowerShell”, digitamos o comando ‘jdb’ – Java Debugging, iniciará o depurador Java e permitirá que utilizemos os recursos de análise de código. O que apresentamos até o momento é a execução do Java Debugging via terminal, mas caso queiramos que a análise de dados seja feita via IDE, mais especificamente o eclipse, precisamos conhecer as funções e onde estão localizados no eclipse. Primeiramente, precisamos indicar os pontos de paradas, conhecidos como breakpoints. Observe na Figura 3 que os pontos de paradas estão presentes nas linhas 8, 10, 13 e 15. Para que sejam adicionados esses pontos, precisamos clicar duas vezes na linha que desejamos, e para remover fazemos a mesma função. Na IDE eclipse, temos o botão bug (inseto), como ilustramos na Figura 4, tal função modifica a perspectiva de visualização da análise do código. O programa vai rodar normalmente até o momento que a execução atingir a linha que estiver marcada com um breakpoint. Se for a primeira vez que roda no modo debug, o Eclipse lhe perguntará se deseja mudar a perspectiva para debug, conforme a Figura 5. Clique em Switch, se preferir marque a caixa de seleção para ele lembrar da sua escolha. Toda vez que a execução se deparar com um breakpoint, ela será interrompida e você poderá ver o conteúdo das variáveis naquele momento. Para ver o conteúdo das variáveis, você pode pairar o cursor por cima do nome de cada uma delas, ou pode também adicioná-las à janela de variáveis, conforme ilustrado na Figura 6, para ver o conteúdo de várias variáveis ao mesmo tempo. Para adicionar uma variável a essa janela, selecione a variável e clique com o botão direito do mouse sobre ela, depois clique em watch. FIGURA 3 – BREAKPOINT FIGURA 4 - BOTÃO BUG (INSETO) 46 O que fizemos até o momento foi o gerenciamento de execução da depuração do código, e com todas essas informações manteremos a confiabilidade do código. A partir do momento que a execução do código se deparar com um breakpoint, você poderá continuar a execução linha por linha, pode entrar ou não em métodos, ou mesmo saindo de métodos a partir de então. Existem as opções correspondentes na barra de tarefas, conforme ilustrado na Figura 7. FIGURA 5 - PERSPECTIVA PARA DEBUG FIGURA 6 - VARIÁVEIS FIGURA 7 - BOTÕES DE GERENCIAMENTO DO DEBUGGING 47 3. TRATAMENTO DE ERROS EM PROGRAMAÇÃO ORIENTADA A OBJETOS Uma das principais vantagens na Programação Orientada a Objetos é permitir que nossos programas funcionem de forma confiável. Quando algo inesperado acontece, é importante que nossos programas possam lidar com isso de maneira adequada, em vez de simplesmente travarem ou apresentarem comportamentos inesperados. Na POO, o tratamento de erros geralmente envolve o uso de exceções. Uma exceção é uma ocorrência anormal que interrompe o fluxo normal de execução do programa. Quando ocorre um erro, uma exceção é lançada e o programa precisa decidir como lidar com ela. Existem várias estratégias para lidar com exceções em POO. Uma abordagem comum é o uso de blocos try-catch, onde o código suscetível a erros é colocado dentro de um bloco try e as exceções são capturadas e tratadas em blocos catch separados. Além disso, é importante que nossas classes e métodos sejam projetados de maneira apropriada para lidar com erros de forma eficiente. Isso pode envolver o uso de validações de entrada para garantir que os dados recebidos estejam corretos, bem como o lançamento de exceções quando condições de erro são detectadas. FIGURA 8 - CÓDIGO TRY-CATCH 48 garantindo que nossos programas lidem adequadamente com situações inesperadas e continuem funcionando de maneira confiável. Em suma, o debugging em POO, juntamente de práticas de tratamento de erros adequadas, é essencial para o desenvolvimento de software robusto e confiável, garantindo que nossos programas funcionem conforme o esperado em diferentes cenários e condições. Considerações Finais O processo de debugging, ou depuração, é crucial na Programação Orientada a Objetos (POO), em que o código é organizado em objetos que interagem entre si por meio de mensagens. Embora essencial, o debugging na POO pode ser desafiador, especialmente devido à complexidade da orientação a objetos, e tudo é representado por objetos que se comunicam entre si. No entanto, com ferramentas de debugging adequadas, como depuradores automáticos, podemos identificar e corrigir problemas durante o desenvolvimento de software orientado a objetos. Essas ferramentas permitem analisar o código em tempo de execução, examinando valores de variáveise identificando possíveis erros de lógica. Além disso, métodos como testes unitários e o Desenvolvimento Orientado a Testes (TDD) são práticas valiosas para identificar e corrigir problemas desde o início do processo de desenvolvimento. O teste de mesa, baseado na Lógica de Programação, também desempenha um papel crucial, permitindo visualizar a execução do programa e desenvolver soluções codificadas para diversos problemas. Com relação ao tratamento de erros em POO, as exceções desempenham um papel fundamental. Por meio de blocos try- catch, podemos capturar e tratar exceções de forma eficiente, 49 Referências CARMONA, Henrique. Teste de mesa. [S. l.], 6 jun. 2013. Disponível em: https://pt.slideshare.net/henriquecarmona/aula- 4-teste-de-mesa DEITEL, P. J.; DEITEL, H. M. Java: como programar. 10. ed. São Paulo, SP: Pearson, 2017. E-book. Disponível em: https:// plataforma.bvirtual.com.br. Encerramento do e-book Chegamos ao fim de nossa disciplina, na qual pudemos refletir sobre a programação orientada a objetos. Por meio do conteúdo apresentado, somos capacitados a modelar o mundo real de uma maneira modular, permitindo a criação de sistemas complexos que são mais fáceis de entender, manter e expandir. Ao abraçarmos os princípios da encapsulação, herança e polimorfismo, abrimos as portas para um código mais flexível, reutilizável e resiliente. No entanto, a verdadeira maestria na arte da programação orientada a objetos vai além do simples uso de classes e objetos. Requer uma compreensão profunda dos conceitos fundamentais e a habilidade de aplicá- los de forma eficaz para resolver problemas do mundo real. É um compromisso constante com a prática, aprendizado e aprimoramento.