Olá, estudante, tudo bem? Seguimos nossa missão de apresentar alguns conceitos de programação de sistemas usando a linguagem de programação Python. Nesta lição, irei explorar a abordagem da programação orientada a objetos (POO) e como ela é implementada na linguagem de programação Python. O objetivo é fornecer uma compreensão fundamental dos conceitos de POO e como eles são aplicados na prática usando a sintaxe e recursos específicos da referida linguagem.
Mas afinal, o que é Orientação a Objetos? Você já deve ter visto em outra lição de outra disciplina em algum momento do curso, mas vamos relembrar aqui que a orientação a objetos é um paradigma de programação que organiza o código em unidades chamadas objetos. Cada objeto combina dados (atributos) e operações (métodos) relacionados em uma única entidade. A POO permite modelar o mundo real de forma mais precisa e criar programas que são mais modulares, reutilizáveis e fáceis de manter.
Você verá assuntos como: conceitos fundamentais, classes em python, atributos e métodos, encapsulamento, herança e polimorfismo. Ao final desta lição, você estará preparado para criar classes, definir atributos e métodos, e compreender como a orientação a objetos é aplicada na linguagem Python. Isso permitirá que você escreva um código mais estruturado, modular e reutilizável, além de estar pronto para explorar conceitos avançados de POO à medida que avança na sua jornada de programação.
O paradigma da orientação a objetos desempenha um papel crucial na resolução de um problema frequentemente encontrado: a complexidade que surge à medida que os projetos de software crescem em tamanho e escopo. Para ilustrar esse desafio, podemos considerar o cenário em que um desenvolvedor se depara com a tarefa de criar um sistema de gerenciamento para uma loja.
Esse sistema precisa gerenciar estoque, rastrear detalhes de pedidos e clientes, calcular preços e descontos de produtos e gerar relatórios de vendas e estoque. Através da POO, é possível criar classes como “Produto”, “Pedido”, “Cliente” e “Relatorio”, cada uma com seus próprios atributos e métodos específicos. Por exemplo, a classe “Produto” pode ter métodos para calcular preços e descontos, enquanto a classe “Pedido” pode rastrear detalhes dos pedidos. Essas classes podem ser organizadas de forma hierárquica e modular, tornando o sistema mais compreensível e manutenível.
A combinação de POO com a linguagem Python, por exemplo, permite resolver desafios complexos de desenvolvimento de software de maneira mais eficiente, promovendo a organização, reutilização e escalabilidade do código. Isso ilustra a poderosa capacidade dessa abordagem para lidar com problemas do mundo real e criar soluções eficazes.
Nesta lição, irei apresentar um case fictício sobre a criação de um aplicativo de biblioteca virtual com implementação de POO. A situação é a seguinte: uma equipe de desenvolvedores está criando um aplicativo de Biblioteca Virtual chamado "Leitura fácil". O objetivo é permitir que os usuários acessem e gerenciem uma vasta coleção de livros digitais. O desafio é criar uma funcionalidade eficiente para gerenciar o histórico de leitura de cada usuário, incluindo detalhes como o progresso de leitura e a data de início. Os problemas levantados foram:
Rastrear o progresso de leitura para cada usuário.
Registrar a data de início da leitura de um livro.
Fornecer uma maneira eficiente de gerenciar o histórico de leitura de cada usuário.
A solução com implementação de POO começou quando a equipe decidiu usar a programação orientada a objetos para resolver esse problema. Eles criam uma classe chamada “Livro” para representar os livros na biblioteca e uma classe “Usuario” para representar os usuários. A classe “Usuario” terá um atributo que armazena o histórico de leitura, contendo instâncias da classe Livro e informações como o progresso de leitura e a data de início.
Sendo assim, através deste case podemos ver uma situação em que através da implementação da orientação a objetos, a equipe conseguiu criar uma funcionalidade robusta para gerenciar o histórico de leitura dos usuários. Cada usuário agora pode ter um histórico personalizado contendo detalhes sobre os livros que estão lendo, o progresso e a data de início. Isso facilita o rastreamento da atividade de leitura de cada usuário e fornece uma experiência personalizada.
A Programação Orientada a Objetos ou POO é um paradigma de programação que se baseia na organização de dados e funcionalidades em unidades chamadas “objetos”. Em POO, os objetos são instâncias de classes, que são como modelos que definem a estrutura e o comportamento dos objetos.
A POO se concentra em tratar entidades do mundo real (como objetos físicos, conceitos abstratos ou sistemas) como objetos no código de programação. Cada objeto tem características (chamadas atributos) e ações (chamadas métodos) associadas a ele. Nos próximos itens você verá os conceitos-chave deste paradigma como: classes, objetos, atributos, métodos, encapsulamento, herança e polimorfismo.
A POO promove conceitos como reutilização de código, modularidade, organização e abstração, tornando-o um paradigma de programação poderoso para criar software complexo e manutenível. É amplamente utilizado em linguagens de programação como Python, Java, C++ e muitas outras. Segundo Feltrin (2022), em POO lidamos com estruturas capazes de moldar o comportamento das variáveis em uso de modo otimizado, consumindo menos recursos, tornando nossas aplicações mais eficientes.
Conforme dito no primeiro item desta lição, provavelmente, você já teve acesso a conceitualização de POO em alguma outra lição passada de alguma outra disciplina. Por isso, meu foco a partir de agora será em como a POO é usada com a linguagem de programação Python.
Classes e objetos são conceitos fundamentais na linguagem de programação Python, e eles desempenham um papel crucial na POO. Uma classe em Python é como um plano ou uma estrutura que define as características (atributos) e comportamentos (métodos) que os objetos desta classe terão. Você pode pensar em uma classe como um molde que nos permite criar objetos com características e comportamentos específicos. A definição de uma classe inclui variáveis para atributos e funções para métodos. Veja a seguir na figura 01 um exemplo de classe e objetos em Python:
Na figura 01, temos um exemplo de classe (Pessoa) e dois exemplos de objetos (pessoa1, pessoa2). Ainda sobre a figura entre a linha 1 e a linha 7 é a criação da classe onde temos o método construtor que recebe dois parâmetros, nome e idade e mais especificamente na linha 6 temos a criação de um método (apresentar) que simplesmente imprime uma frase já buscando dados preenchidos do objeto.
Atributos e métodos desempenham papéis cruciais na definição e manipulação de objetos. Atributos são variáveis associadas a objetos de uma classe. Feltrin (2022) afirma que um atributo de classe nada mais é do que uma variável declarada dentro de uma classe. Eles representam as características ou propriedades do objeto. Cada objeto de uma classe pode ter seus próprios valores de atributos, mas todos os objetos dessa classe compartilham a mesma estrutura de atributos definida na classe.
Para criar atributos em uma classe Python, você pode simplesmente definir variáveis dentro da classe. Essas variáveis são chamadas de “atributos de instância” e podem ser acessadas usando a notação de ponto em objetos dessa classe como você pode conferir na Figura 01 do item anterior, mais precisamente nas linhas 03 e 04.
Já os métodos são funções definidas em uma classe que representam o comportamento do objeto, eles definem ações que objetos dessa classe podem realizar. Feltrin (2022) diz, em outras palavras, que métodos são funções criadas dentro de uma classe, que de modo geral, servem para realizar certas ações iterando sobre os próprios objetos da classe. Os métodos podem acessar e modificar os atributos de um objeto e realizar outras operações.
Para criar métodos em uma classe Python, você define funções dentro da classe. Esses métodos podem ser chamados de objetos dessa classe usando a notação de ponto como você pode conferir na Figura 01, mais precisamente nas linhas 06 e 07 e depois nas linhas 11 e 12.
Sendo assim, atributos e métodos são essenciais na criação de classes e objetos que modelam entidades do mundo real e na definição de seu comportamento. Eles permitem a organização e a interação de dados de forma estruturada, tornando a POO uma abordagem poderosa para desenvolver softwares modulares e reutilizáveis em Python e em outras linguagens.
O encapsulamento é o conceito de ocultar os detalhes internos de uma classe e disponibilizar uma interface controlada para interagir com essa classe. Ele permite que os atributos e métodos de uma classe sejam acessados e modificados somente de acordo com as regras definidas pela própria classe. Isso evita que dados sejam corrompidos ou acessados indevidamente, promovendo a integridade dos objetos. O encapsulamento é um dos princípios (pilares) fundamentais da POO e desempenha um papel crucial na criação de código robusto e seguro. Em Python, o encapsulamento é uma técnica que permite controlar acesso aos atributos e métodos de uma classe, restringindo o acesso direto a eles.
Em Python, o encapsulamento é implementado usando convenções de nomenclatura e modificadores de acesso como:
Convenções de nomenclatura: Atributos ou métodos que são destinados a serem privados são prefixados com um sublinhado simples (por exemplo: _atributo_privado).
Métodos Getters e Setters: Em vez de permitir o acesso direto a atributos privados, é uma prática comum fornecer métodos “getters” e “setters” que permitem ler e modificar esses atributos de maneira controlada.
Veja um exemplo de encapsulamento em Python na figura 02:
Mais especificamente na linha 3, é criado o atributo privado _nome e na sequência você consegue obter o valor desse atributo de forma externa através do método getter da linha 5, e atualizar o valor deste atributo através do método setter definido na linha 8.
A herança é um dos pilares fundamentais da POO que desempenha um papel crucial na organização e reutilização de código. Em Python, uma linguagem de programação orientada a objetos, a herança é implementada de maneira elegante e eficaz, permitindo que classes filhas (subclasses) herdem atributos e métodos de classes pai (superclasses). Observe algumas definições do que foi dito no parágrafo anterior:
Superclasse (classe pai): É uma classe existente que serve como modelo para criar outras classes. Ela contém atributos e métodos que podem ser herdados por suas subclasses.
Subclasse (classe filha): É uma nova classe que é criada com base em uma superclasse. Ela herda os atributos e métodos da superclasse e pode adicionar ou modificar funcionalidades conforme necessário.
Herança: A herança é o processo pelo qual uma classe filha herda atributos e métodos de uma classe pai. Isso promove a reutilização de código e a criação de hierarquias de classes.
Veja na Figura 03 a sintaxe básica de herança na linguagem de programação Python:
O que você pode observar de mais importante na figura 03 está na linha 9, onde na definição da subclasse passamos a superclasse como argumento que é a sintaxe Python para indicar a herança, e na linha 11 onde chamamos o construtor da classe pai para atribuir os valores passados para os atributo1 e atributo2.
Polimorfismo é um dos princípios fundamentais da Programação Orientada a Objetos (POO) que permite que objetos de diferentes classes sejam tratados de maneira uniforme, desde que eles tenham uma interface comum. Em outras palavras, o polimorfismo permite que diferentes tipos de objetos sejam usados de forma intercambiável quando eles respondem a métodos comuns.
O termo "polimorfismo" se origina das palavras gregas "poly" (muitos) e "morphos" (formas). Em programação, o polimorfismo permite que objetos de diferentes classes se comportem de maneira diversificada com base em suas próprias implementações de métodos, enquanto mantêm uma interface comum. O polimorfismo pode ser implementado de duas maneiras em Python:
Polimorfismo de método: Isso ocorre quando duas ou mais classes têm métodos com o mesmo nome, mas as implementações desses métodos são diferentes em cada classe. O comportamento do método depende do objeto chamado.
Polimorfismo de operador: Python permite que operadores como +, -, * e outros se comportem de maneira diferente para tipos de objetos diferentes. Por exemplo, o operador + pode ser usado para concatenar (unir) strings e somar números inteiros.
A orientação a objetos em Java é um paradigma de programação fundamental, proporcionando uma abordagem estruturada para o desenvolvimento de software, sendo assim, é um conteúdo muito importante para você estudante do curso Técnico em Desenvolvimento de Sistemas. O que vimos hoje na lição são apenas alguns conceitos básicos da orientação a objetos em Java, e o que você precisa ter em mente é que a combinação desses elementos permite a criação de sistemas robustos, flexíveis e de fácil manutenção.
Agora chegou a sua vez de colocar os seus conhecimentos em práticas e criar algumas classes do case desta lição. Primeiro, você irá acessar o ambiente para codificar, neste caso vamos usar o site OnlineGDB que pode ser acessado através do link (https://www.onlinegdb.com/). Com o site aberto você irá selecionar no canto superior direito na opção Language a linguagem de programação Python 3. Selecione todo o código que vem automaticamente no arquivo main.py e digite o seguinte código conforme a figura 4:
O funcionamento do código da figura 1 possui o seguinte fluxo:
Linhas 1 a 4: Criação da classe Livro que recebe pelo seu construtor valores para título e autor.
Linhas 6 a 9: Criação da classe Usuario que recebe pelo seu construtor valores para nome e inicializa o atributo historico_leitura como uma lista vazia.
Linhas 11 e 12: cria o método adicionar_leitura que recebe um livro, um valor para progresso e um valor para data de início de leitura adicionando esses valores ao histórico de leitura.
Linhas 14 a 16: Instância 3 objetos do tipo livro e seus respectivos valores.
Linhas 18 e 19: Instância 2 objetos do tipo usuario.
Linhas 21 e 22: adiciona progressos de leitura dos dois livros criados para o usuario1.
Linhas 24 e 25: adiciona progressos de leitura dos dois livros criados para o usuario2.
Linhas 27 a 33: através de um laço de repetição (for) itera entre os usuários e depois pelo histórico de leitura para exibir algumas informações na tela do usuário.
FELTRIN F. Programação Orientada à Objetos em Python: do básico ao avançado. 1. Uniorg, 2022.