Prévia do material em texto
Métodos de programação
APRESENTAÇÃO
Conhecer e entender os métodos e tipos de programação é um desafio instigante e, de certa
forma, um compromisso de todo profissional de desenvolvimento de software. Ao compreender
os conceitos que levam ao desenvolvimento de diferentes paradigmas, é possível apresentar
maior discernimento quanto à adoção de uma linguagem de programação que atenda a uma
determinada necessidade.
Nesta Unidade de Aprendizagem, você vai conhecer a evolução
dos principais tipos de métodos de programação e o seu histórico
de desenvolvimento.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Definir métodos de programação.•
Sintetizar o histórico dos métodos de programação.•
Identificar os tipos de métodos de programação.•
DESAFIO
Os paradigmas de programação são diferentes classificações atribuídas à estruturação de
linguagens de programação. Ao longo do desenvolvimento da computação, surgiram vários
paradigmas e, consequentemente, novas linguagens de programação que empregavam seus
conceitos na forma de se estruturar, o que também impactou os profissionais da área, uma vez
que é comum um profissional mais novo achar estranho trabalhar com uma linguagem
embasada em um paradigma de décadas atrás.
Imagine que você trabalha em uma equipe de desenvolvimento de softwares em uma
organização que já trabalha há muito tempo com softwares desenvolvidos internamente, com
linguagens de programação da década de 90, como Visual Basic 5.0 e Delphi 6.0.
Na sua equipe há um programador mais novo que começou a trabalhar com linguagens
orientadas a objetos, principalmente com Java, e que encontrou uma dificuldade na adaptação ao
paradigma de linguagens estruturadas.
Você, como programador mais experiente, deve explicar ao programador:
a) A diferença entre os dois paradigmas.
b) O porquê de, ao contrário do Java, não ser possível desenvolver com as linguagens de
paradigma estruturado Visual Basic 5.0 e Delphi 6.0.
INFOGRÁFICO
Aprender sobre a evolução dos paradigmas de programação e entender o caminho percorrido até
os recursos atuais de programação é, além de instigante, necessário para o profissional de
programação.
A seguir, no Infográfico, veja a evolução das linguagens e dos paradigmas de programação e os
desafios já transpostos ao longo dos anos pelos projetistas, engenheiros de computação
e comunidade de desenvolvedores.
CONTEÚDO DO LIVRO
Os métodos de programação fazem parte da história da programação, assim como as linguagens
e tecnologias relacionam-se à arte de programação. Esses paradigmas contam muito da evolução
e de como a ciência ao longo do tempo desenvolveu meios mais próximos das necessidades de
programação propostas à comunidade.
Leia o capítulo Métodos de programação, da obra Paradigmas de programação, e conheça um
pouco mais sobre a evolução dos paradigmas de programação, veja os tipos existentes e entenda
seus conceitos e sua relação com as linguagens que surgiram ao longo do tempo.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Métodos de programação
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Explicar o que são métodos de programação.
� Sintetizar o histórico dos métodos de programação.
� Identificar os tipos de métodos de programação.
Introdução
Em geral, quando se trata do tema paradigmas de programação, não
se atribui a devida importância para o assunto. Todo o profissional de
programação de computadores deveria se atentar aos diferentes para-
digmas, pois eles são a base para as diferentes linguagens que existem
e existiram ao longo da evolução da programação.
É comum pensar, como estudantes ou profissionais, quais os be-
nefícios de entender os conceitos de linguagens de programação em
uma área com tantos temas muito pertinentes, mas saber como uma
linguagem funciona para interpretar as instruções e a evolução de lin-
guagens e conceitos ao longo do tempo, sem dúvidas, traz vantagens
na construção de softwares.
Neste capítulo, você aprenderá o que são os métodos de programa-
ção, quais são os diferentes tipos e como ocorreu a sua evolução.
Paradigmas de programação
Como seres humanos, sentimos necessidade de expressar nossos pensamentos,
seja de forma verbal, utilizando o nosso poder de comunicação, ou escrita,
escrevendo textualmente o que estamos pensando. A linguagem de progra-
mação, assim como a nossa linguagem natural, permite nossa comunicação
com as máquinas. Dessa maneira, podemos instruir, por meio de linhas de
comandos, as máquinas a executarem determinada instrução.
No entanto, para Tucker e Noonan (2009), as linguagens de programação
se diferem das linguagens naturais de duas maneiras importantes. Apesar
de permitirem a comunicação entre humanos e máquinas, elas possuem um
domínio de expressão mais reduzidos do que as linguagens naturais, pois
seu objetivo é permitir a compreensão de ideias computacionais, ou seja, se
propõem a atender diferentes requisitos das linguagens naturais.
Toda a linguagem de programação está construída sobre um paradigma.
Mas, afinal, o que é um paradigma? Um paradigma representa um padrão de
pensamento que guia um conjunto de atividades relacionadas, trata-se de um
padrão que define um modelo para a resolução de problemas e regra, basica-
mente, toda e qualquer linguagem de programação existente. Os paradigmas
de programação estão classificados em quatro diferentes tipos, que evoluíram
ao longo das últimas décadas:
� programação imperativa;
� programação funcional;
� programação lógica;
� programação orientada a objetos.
A Figura 1 ilustra de forma hierárquica os diferentes paradigmas de pro-
gramação atuais e sua derivação dos paradigmas imperativo e declarativo.
Figura 1. Paradigmas de programação.
Fonte: Adaptada de Simão (2018).
Paradigma de programação
Paradigma imperativo Paradigma declarativo
Paradigma
procedimental
Paradigma
funcional
Programação
baseada em
regras
Paradigma
lógico
Paradigma
orientado a
objetos
Programação
orientada a
eventos
Métodos de programação2
Algumas linguagens de programação foram projetadas para suportar diferentes
paradigmas. Um exemplo disso, é o da linguagem de programação C++, que foi
projetada para ser uma linguagem imperativa e orientada a objetos.
No início da programação, o único meio de conseguir programar um
computador era inserindo um código binário de programas para a sua me-
mória principal, o que representava uma grande probabilidade de erros e uma
manutenção praticamente impossível. Nessa época, escrevia-se programas
utilizando linguagens de baixo nível, porém, com a popularidade dos computa-
dores, as demandas por softwares se tornaram enormes. Então, as linguagens
necessitaram evoluir para um paradigma de nível mais alto, sendo a evolução
dos métodos e linguagens uma consequência dessa demanda.
Na próxima seção, você verá um pouco da evolução dos paradigmas de
programação ao longo das décadas e o surgimento de diferentes linguagens
que possibilitaram o desenvolvimento de softwares com melhor compreensão
e manutenção do que os existentes no início da programação.
Histórico dos métodos de programação
No início da programação de computadores, as primeiras linguagens disponí-
veis eram as de máquinas e as próprias linguagens de construção (Assembly)
dos primeiros computadores. A partir delas, muitas linguagens de programa-
ção e dialetos foram desenvolvidos, algumas obtiveram sucesso e inclusive
influência sobre outras linguagens e, naturalmente, outras tiveram um tempo
de vida limitado Sebesta (2018).
A programação de computadores não tem uma data correta de início. Na
década de 1930, surgiram os primeiros computadores elétricos; já em 1948,
Konrad Zuse publicou sua criação, a linguagem de programação Plankalkül.
Nessa época, ela ainda não tinha muita utilidade, então, foi esquecida. Con-
tudo,antes da programação passar para o computador, eram usados cartões
de papelão, que eram perfurados, criando códigos.
3Métodos de programação
Os paradigmas da programação foram criados, em sua maioria, na década
de 1970. Nessa época surgiram as seguintes linguagens:
� Simula — inventada nos anos de 1960 por Nygaard e Dahl, foi a primeira
linguagem a suportar o conceito de classes;
� C — foi uma das primeiras linguagens de programação de sistemas,
criado por Dennis Ritchie e Ken Thompson, tem uma das maiores
influências no mundo atual;
� Prolog — projetada em 1972, foi a primeira linguagem de programação
com paradigma lógico;
� Pascal — foi muito importante, mas atualmente está quase sem uso;
� C++ — criada para ser compatível com C, foi muito importante, pois
é mais simples e dinâmica;
� Perl — é uma boa linguagem para trabalhar em níveis de sobrecarga
grandes.
Nos anos de 1990, a internet surgiu como um furacão, mudando totalmente
o rumo da programação. As linguagens Java e JavaScript foram criadas nessa
época, ambas relacionadas à internet. Na mesma época, surgiram a Visual
Basic e o Object Pascal.
Java é uma linguagem relativamente simples, orientada a objetos, criada com
o intuito de revolucionar as linguagens de programação. Já PHP (acrônimo para
“pré-processador de hipertexto”) é muito importante para o desenvolvimento
de aplicativos para Web, é a linguagem que, cada vez mais, toma conta dos
websites (MILETTO; BERTAGNOLLI, 2014).
Na Figura 2, você verá um breve resumo histórico da evolução e da in-
fluência de algumas linguagens de programação sobre outras. Apesar desse
histórico não ser completo, é possível perceber alguns eventos e tendências
mais influentes.
Métodos de programação4
Figura 2. Resumo da história das linguagens de programação.
Fonte: Tucker e Noonan (2009, p. 7).
A década de 1950 marcou a chegada das linguagens de alto nível. Essas
linguagens se diferenciavam das linguagens de máquina por não estarem dire-
tamente dependentes de uma arquitetura específica. As primeiras linguagens
que chegaram com essa característica foram Fortran, Cobol, Algol e Lisp.
Fortran e Cobol foram linguagens que alcançaram um grande sucesso e
possuem, até hoje, um grande legado de sistemas escritos que atuam inclusive
em grandes organizações, como segmento financeiro. Já Lisp foi caindo em
desuso e Algol praticamente sumiu (MILETTO; BERTAGNOLLI, 2014).
5Métodos de programação
Certamente, o maior motivador para o desenvolvimento das linguagens
e métodos de programação nas últimas décadas tem sido o rápido desenvol-
vimento dos recursos computacionais e o surgimento de novas e emergentes
tecnologias, entre as quais podemos destacar as seguintes áreas:
� inteligência artificial;
� World Wide Web ;
� sistemas e redes;
� dispositivos móveis.
Ao contrário do que costumamos imaginar, a programação funcional não é o oposto
de programação orientada a objetos. São tipos diferentes de programação, mas
podem, inclusive, ser usadas em uma mesma aplicação, principalmente em linguagens
multiparadigmas, como o JavaScript.
O projeto de uma nova linguagem de programação é algo bem complexo,
o projetista deve se preocupar com inúmeros desafios e adotar soluções es-
pecíficas, que se proponham a atender esses desafios. Os principais desafios
envolvidos no projeto de uma nova linguagem de programação são:
� arquitetura;
� requisitos técnicos;
� padrões.
Entre os desafios propostos aos projetistas, vamos destacar os padrões.
Sempre que uma linguagem de programação tem um amplo uso entre os
desenvolvedores, é natural que novo processo de padronização surja, ou
seja, a comunidade define um padrão de construção independentemente da
máquina da linguagem e que todos os seus programadores devem aderir. Isso
é importante porque o método de padronização, entre outras vantagens, busca
a estabilização em diferentes plataformas, possibilitando a portabilidade dos
programas construídos a partir dela.
Métodos de programação6
Se observarmos essa evolução, é possível perceber que algumas lingua-
gens que obtiveram sucesso foram projetadas por comunidades ou grupos de
desenvolvedores, exigindo uma certa padronização quanto aos programas
construídos.
Tipos de programação
Os tipos de programação estão diretamente relacionados ao conceito do para-
digma no qual a linguagem foi concebida, por exemplo é impossível utilizar
uma linguagem linear como Ada ou Assembly e tentarmos construir um
programa com blocos de funções. Isso acontece porque o paradigma desse
tipo de linguagem não provê recursos que o paradigma procedural possibilita,
permitindo o reuso de código por meio de funções (blocos que executam uma
determinada funcionalidade).
Portanto, é importante entender e conhecer bem os tipos de paradigmas de
programação e seus conceitos, para que ao utilizar uma linguagem se saiba
como, de acordo com o tipo de paradigma em que ela foi concebida, devem
ser estruturados os códigos. A seguir você verá os tipos de paradigmas que
surgiram ao longo da evolução da programação.
Paradigma imperativo
Após a geração de programação linear com linguagens de máquina, houve
um grande avanço com o advento das linguagens procedurais. Esse tipo de
paradigma foi o primeiro que apresentou as linguagens de alto nível, que
permitiam a utilização de um vocabulário mais próximo ao natural para
construção de programas. Esse paradigma recebe o nome de imperativo pela
forma como as instruções nos códigos são repassadas para o compilador:
� Faça isso.
� Depois faça aquilo.
7Métodos de programação
É uma forma imperativa de dar ordens para que a máquina execute as
instruções dadas, e ela executará cada uma, passo a passo, com o propósito
de chegar no resultado esperado. Uma linguagem imperativa suporta algumas
características comuns:
� atribuições, declarações e expressões;
� estruturas de controle;
� abstração procedural.
Basicamente, os códigos são construídos obedecendo a estrutura de de-
clarações e as instruções. A linguagem mais popular desse paradigma é a
linguagem C (MILETTO; BERTAGNOLLI, 2014).
Paradigma declarativo
A principal característica das linguagens com programação declarativa é o
foco não estar em como uma execução vai ocorrer, mas sim no resultado a
ser atingido. Um dos melhores exemplos para entender esse paradigma são
as instruções structured query language (SQL), pois nela são passados para
o banco de dados apenas o que se pretende, sem a preocupação sobre como
o banco de dados vai executar a instrução, o foco é somente o retorno ou
resultado da consulta.
Atualmente, uma das principais linguagens de programação utilizada, o
framework JavaScript Angular, é um exemplo de implementação desse para-
digma, que, aliás, é muito utilizado em razão do advento dos sistemas Web,
no qual o código submete uma execução e espera o retorno.
Paradigma estruturado
No sentido mais restrito, o conceito de programação estruturada se refere à
forma do programa e do processo de codificação. É um conjunto de convenções
que o programador pode seguir para produzir o código estruturado, e suas
regras de codificação impõem limitações sobre o uso das estruturas básicas
de controle, estruturas de composição modular e documentação.
Métodos de programação8
As características do paradigma estruturado são:
� programação sem GOTO (eliminação completa ou parcial do comando
GOTO, que significa “ir para”);
� programação com apenas três estruturas básicas de controle — sequên-
cia, seleção e iteração;
� forma de um programa estruturado;
� aplicação de convenções de codificação estruturada a uma linguagem
de programação específica.
Algumas linguagens com esse paradigma são Pascal e C.
Paradigma orientado a objetos
O paradigma de orientação a objetos surge como o advento da reutilização de
código e a facilidade na manutenção. No paradigma de orientação a objetos,
o princípio é a construção de código, implementando as entidades do mundoreal por meio do conceito de classes que possuem relação entre si.
Como o desempenho das aplicações não é uma das grandes preocupações
na maioria delas (devido ao poder de processamento dos computadores atuais),
a programação orientada a objetos se tornou muito difundida. A programação
orientada a objetos está embasada em quatro pilares.
� Abstração: como estamos lidando com objetos do mundo real, por exem-
plo, carro, casa, pessoa etc.), precisamos imaginar como esses objetos
vão se integrar dentro do nosso sistema e modelar seu comportamento
abstraindo comportamento e características específicas de cada um.
� Encapsulamento: não importa para um código que invoca um método
saber como outro vai ser executado, trata-se de uma característica que
traz principalmente segurança ao código.
� Herança: assim como no mundo real, a herança em programação orientada
a objetos seria a capacidade de uma classe herdar de outra métodos e atri-
butos, sendo, portanto, uma característica relacionada ao reuso de código.
� Polimorfismo: existem animais capazes de se adaptar a algumas ne-
cessidades do mundo real e se comportar de forma diferenciada em
alguns casos, essa particularidade também é possível no paradigma
de orientação a objetos. Mesmo herdando o comportamento de outra
classe, a classe herdeira pode modificar o seu comportamento em de-
terminadas situações.
9Métodos de programação
Por ser algo muito abstrato, a programação orientada a objetos é difícil de aprender.
Vários conceitos são artificiais e isso torna o aprendizado bastante complicado. O
resultado que se vê é muito código não orientado ao objeto, mas escrito em linguagens
orientadas a objetos.
Para atender a diversidade e complexidade do universo da programação
é que os paradigmas são divididos. É importante salientar que não existe um
paradigma vinculado à determinada linguagem de programação, o paradigma
tem que ser independente de linguagem. Por exemplo, a orientação a objetos
é um paradigma criado para a solução de problemas de desenvolvedores e
não tem uma ligação de necessidade com nenhuma linguagem, quem aborda
esses paradigmas são as linguagens de programação. Você pode observar
que várias linguagens de programação abordam vários tipos de paradigma
de programação.
A escolha do melhor paradigma é necessariamente relacionada ao tipo de
problema que precisa ser solucionado.
Veja no link a seguir um site sobre os pilares e conceitos do paradigma de programação
orientada a objetos.
https://qrgo.page.link/JBCZA
MILETTO, E. M.; BERTAGNOLLI, S. C. Desenvolvimento de software II: introdução ao de-
senvolvimento web com HTML, CSS, JavaScript e PHP. Porto Alegre: Bookman, 2014.
276 p. (Série Tekne; Eixo Informação e Comunicação).
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
Métodos de programação10
SIMÃO, J. M. Orientação a objetos: programação em C++. Curitiba: Departamento Acadê-
mico de Eletrotécnica, Universidade Federal Tecnológica do Paraná, 2018. 26 p. (Notas
de aula). Disponível em: http://www.dainf.ct.utfpr.edu.br/~jeansimao/Fundamentos1/
LinguagemC++/Fundamentos1-2-SlidesC++1-A-2018-08-01.pdf. Acesso em: 25 ago. 2019.
TUCKER, A. B.; NOONAN, R. E Linguagens de programação: princípios e paradigmas.
2. ed. Porto Alegre: AMGH, 2009. 630 p.
Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
NEGRESIOLO, L. Tudo o que você precisa (e deveria) saber sobre Programação Orien-
tada a Objetos. Gizmodo Brasil, São Paulo, 22 jan. 2019. Disponível em: https://gizmodo.
uol.com.br/tudo-sobre-programacao-orientada-a-objetos/. Acesso em: 25 ago. 2019.
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
11Métodos de programação
DICA DO PROFESSOR
Para desenvolver uma solução é necessário que se conheça tanto o problema quanto os tipos de
paradigmas de programação existentes. Apenas assim, pode ser entregue um produto que atenda
aos objetivos determinados.
A seguir, na Dica do Professor, saiba um pouco mais sobre a importância dos paradigmas de
programação.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) É natural que estudantes da área de computação questionem o porque de se estudar
os conceitos e a história das linguagens de programação, no entanto, adquirir esse
conhecimento proporciona ao aluno e futuro profissional diversas vantagens.
Assinale a alternativa que expresse algumas dessas vantagens:
A) Embasamento para escolha de linguagens adequadas e melhor entendimento da
importância da implementação.
B) Facilidade de comunicação com outros desenvolvedores e reúso de componentes.
C) Preparação para certificações e reúso de componentes.
D) Aumento da capacidade de raciocínio lógico e conhecimento geral.
E) Delegação de responsabilidades e reaproveitamento de códigos.
2)
Computadores têm sido utilizados para uma infinidade de áreas que, por sua vez,
resultam no desenvolvimento de novos conceitos e linguagens que demandam novos
paradigmas e métodos de programação. Assinale a alternativa correta sobre algumas
das áreas que impulsionaram esse desenvolvimento:
A) Indústria Automobilística e Comércio Eletrônico.
B) Medicina e Inteligência Artificial.
C) Inteligência Artificial e World Wide Web.
D) Dispositivos Móveis e Governo.
E) Inteligência Artificial e Governo.
3) As linguagens de programação podem apresentar características e comportamentos
definidos de acordo com o paradigma que a construiu. No entanto, uma linguagem
pode apresentar características provenientes de diferentes paradigmas. Dessa forma,
assinale a alternativa verdadeira:
A) Os paradigmas não estão vinculados à linguagem de programação.
B) As linguagens de programação são as responsáveis na definição de um paradigma.
C) O paradigma de orientação a objetos foi o precursor do conceito de reusabilidade de
código.
D) No paradigma estrutural, não importa o COMO e sim O QUE se pretende alcançar com o
código do programa.
E) Para escolher o melhor paradigma, deve-se levar em consideração a tecnologia e não o
contexto do problema que se deseja resolver.
4) O paradigma de programação imperativo tem como principal característica a
declaração comandos, que descreve uma sequência de instruções para alcançar um
objetivo. Sobre os conceitos do paradigma imperativo, assinale a alternativa correta:
A) A programação imperativa não possibilita trabalhar com reúso de código.
B) A programação imperativa é um paradigma ultrapassado que não tem mais uso.
C) A programação imperativa não foca na resolução do problema, nem nas instruções.
D) A programação imperativa apresenta linguagens amplamente utilizadas, como a linguagem
C, por exemplo.
E) A programação imperativa tem o foco em entender os comandos sem seguir uma lógica.
5) O paradigma de programação estruturada surgiu com a ideia da criação de
estruturas e blocos de execução de rotinas e foi amplamente utilizado, dando ênfase
para o surgimento do paradigma orientado a objeto. Assinale a alternativa correta
sobre o paradigma de programação estruturada:
A) O paradigma estruturado foi substituído pelo orientado a objetos.
B) O paradigma estruturado não permite a reutilização de código.
C) O paradigma estruturado permite recursos como herança e polimorfismo.D) O paradigma estruturado trabalha com conceito de classes e funções.
E) O paradigma estruturado permite a organização do código em estruturas funcionais.
NA PRÁTICA
Ao iniciar o aprendizado em uma nova linguagem de programação, é importante conhecer,
além dos recursos e e da sintaxe, a sua arquitetura e suas vantagens ou desvantagens. Neste
contexto, conhecer o paradigma em que a linguagem foi construída torna-se um atalho para a
tarefa.
A seguir, no Na Prática, veja as características e vantagens da utilização do paradigma orientado
a objetos.
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Informações sobre paradigmas de programação
No vídeo a seguir, você vai encontrar de forma resumida e didática algumas informações
relacionadas aos paradigmas de programação.
Conteúdo interativo disponível na plataforma de ensino!
Definições de programação imperativa, declarativa e reativa
Neste artigo, você vai encontrar uma definição sucinta de programação imperativa, programação
declarativa e de programação reativa, um paradigma relativamente novo.
Conteúdo interativo disponível na plataforma de ensino!
História da programação
Neste artigo, você vai conhecer um pouco da história da programação, passando por décadas de
evolução, diferentes paradigmas e linguagens.
Conteúdo interativo disponível na plataforma de ensino!
Programação declarativa
APRESENTAÇÃO
A programação declarativa tem como principal característica a possibilidade de programar de
acordo com o objetivo a ser atingido. Assim, a programação acontece a partir do resultado que
se deseja obter com o programa e não com foco no que será executado, para atingir o resultado
esperado. É um tipo de programação em que o programa deve declarar os objetivos da sua
execução.
Nesta Unidade de Aprendizagem, você vair definir conceitualmente
o que é programação declarativa, identificar algumas linguagens
de programação declarativa e verificar algumas aplicações
desse paradigma.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Definir programação declarativa.•
Identificar as linguagens de programação declarativa.•
Aplicar a programação declarativa.•
DESAFIO
A programação declarativa é um paradigma de programação que possibilita desenvolvimento
mais objetivo, pois o desenvolvedor precisa especificar apenas o que deseja obter de resultado
com o programa. Dentro desse contexto, aplicações clientes servidor, como, por exemplo,
WebService, têm ampla adesão.
Você, como desenvolvedor da equipe de desenvolvimento da companhia, tem como desafio um
novo projeto de integração entre dois sistemas.
O seu sistema deve se integrar com um WebService responsável por fazer o cálculo e a geração
da folha de pagamento. Sendo assim, o sistema deverá enviar um arquivo XML com os dados
dos funcionários, como ponto e férias, e receber outro aquivo XML de retorno com os dados da
folha de pagamento gerada.
Diante desse cenário, como a programação declarativa pode atender essa necessidade? Justifique
a adequação realizada para o escopo do projeto.
INFOGRÁFICO
A programação declarativa surgiu como uma forma de construção de código focado em
especificar o que você deseja alcançar e não em como. Oriunda de estudos matemáticos de
alguns pesquisadores e com o objetivo de atender demandas mais específicas, como a
Inteligência Artificial, ela vem sendo utilizada desde então. E, ao longo do tempo, algumas
linguagens surgiram como expoentes nesse paradigma.
Confira, no Infográfico, um pouco mais sobre os conceitos desse paradigma e algumas
linguagens que se aplicam aos tipos funcional e lógico.
CONTEÚDO DO LIVRO
As linguagens de programação que seguem o paradigma declarativo têm como característica a
construção dos programas orientados para a meta que devem alcançar e não como executarão o
passo a passo para alcançarem essas metas. Por isso, são linguagens que se tornam mais fáceis
de aprender, além de serem amplamente utilizadas no mercado, como SQL, por exemplo.
No capítulo Programação declarativa, da obra Paradigmas de Programação, você
vai compreender o significado do paradigma de programação declarativa, identificando
as linguagens de programação mais utilizadas e suas respectivas aplicações.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação declarativa
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Definir programação declarativa.
� Identificar as linguagens de programação declarativa.
� Aplicar a programação declarativa.
Introdução
Na década de 1970, a programação declarativa surgiu como um novo
paradigma para a área da programação, diferente dos já existentes, pois
exigia que o programador informasse quais os objetivos pretendidos
com a computação. Essa ação era contrária a apenas escrever algoritmos
detalhados descrevendo como os objetivos poderiam ser alcançados.
Dessa forma, a programação declarativa se constituiu como um para-
digma em que as linguagens de programação mantêm a característica de
aprendizagem mais fácil do que a linguagem de programação imperativa.
Neste capítulo, você entenderá melhor as características da progra-
mação declarativa e identificará algumas linguagens declarativas e sua
aplicação.
Programação declarativa
A linguagem de programação declarativa surgiu como um novo paradigma
de construção de programas, diferente da linguagem de programação impe-
rativa, na qual a construção de um programa ocorre por meio da construção
de algoritmos complexos que descrevem passo a passo como um determinado
resultado é alcançado, nesse paradigma, o foco está em descrever quais os
resultados devem ser alcançados. Segundo SEBESTA (2018), a programação
declarativa requer que o programador foque nos objetivos da computação, e
não em como esses objetivos serão alcançados.
As aplicações construídas seguindo o paradigma da linguagem declarativa
são classificadas em dois domínios principais, conforme descrito a seguir.
� Aplicações de inteligência artificial: no campo da inteligência artificial é
fácil imaginar porque esse paradigma se adapta bem, pois são aplicações
que se preocupam com os objetivos, utilizando regras e lógicas. Nesse
domínio a linguagem Prolog tem sido um destaque.
� Aplicações de acesso de informações em banco de dados: os maiores
usos de linguagens de programação declarativa estão concentrados no
domínio de consultas e manipulação de dados em sistemas de gestão
de base de dados (SGBD), a structured query language (SQL), por
exemplo, se tornou o expoente desse uso.
Na programação declarativa, podemos dizer que um programa é um con-
junto de declarações, por exemplo, verdade, falso, satisfaz restrição etc. O
conceito fundamental e o foco devem estar sempre na declaração, mas a sequ-
ência não importa. Além disso, é comum dizer que a programação declarativa
se distingue da programação imperativa no sentido de apenas especificar o
que, ao contrário de especificar o como.
As linguagens de programação declarativas ainda podem ser subdividas em
funcional e lógica. O Prolog se destaca como um exemplo de linguagem decla-
rativa e lógica no paradigma de linguagem declarativa e funcional. Linguagens
de cálculos, como o LISP é um exemplo disso (TUCKER; NOONAN, 2009).
A Figura 1 ilustra os diferentes tipos de programação declarativa.
Figura 1. Diferentes tipos de programação declarativa.
Fonte: Adaptada de Botelho (2015).
Programação declarativa2
Ainda no escopo de programação lógica, que é um dos tipos de programa-
ção declarativa, um programa é um conjunto de afirmações sobre as várias
entidades do domínio da aplicação. Já na programação funcional pura, um
programa é constituído por apenas um conjunto de definições de funções, e
cada função é definida sempre em razão de outras funções.
Linguagens de programaçãodeclarativa
A primeira linguagem de programação funcional a surgir foi inventada para
fornecer recursos para o processamento de listas, uma necessidade impulsionada
pelo surgimento das primeiras aplicações na área de inteligência artificial. A
programação lógica é caracterizada pelo uso de uma notação lógica formal para
comunicar processos computacionais para um computador. O cálculo de predi-
cados é, atualmente, a notação utilizada nas linguagens de programação lógica.
As linguagens de programação funcionais e lógicas são tipos de linguagens
de programação. A seguir vamos detalhar mais as linguagens funcionais LISP
e lógica Prolog, que são as principais nos seus respectivos tipos.
Linguagem de programação LISP
O interesse na área de inteligência artificial no início dos anos de 1950 fomentou
a necessidade do processamento de listas, provindas a partir da linguística, da
psicologia e da matemática (SEBESTA, 2018). Cada área tinha seu interesse
específico, os linguistas estavam interessados no processamento da linguagem
natural, os psicólogos em modelar o comportamento e os matemáticos em
mapear processos de raciocínio mental. Todos chegaram a uma conclusão em
comum: era necessário criar uma forma de permitir o processamento dados
simbólicos em listas encadeadas pelo computador. Na época, a maior lista da
computação era constituída por dados numéricos armazenados em vetores.
A linguagem de programação LISP surgiu dos estudos realizados por John
McCarthy no Massachusetts Institute of Technology (MIT). Sua primeira
versão foi chamada de LIST puro, por ser uma linguagem puramente funcional.
Essa versão do LIPS trabalhava com apenas três tipos de dados:
� Átomos, que são símbolos com a forma de identificadores ou literais
numéricos.
3Programação declarativa
� Listas, que são especificadas com a delimitação de seus elementos
com parênteses, nos quais os elementos são restritos a átomos, tendo
o seguinte formato: (A B C D).
� Estruturas de listas aninhadas, também especificadas com parênteses,
por exemplo, (A (B C) D (E (F G))), que é composta de quatro elemen-
tos. O primeiro elemento é o átomo A; o segundo, é a sub lista (B C);
o terceiro, é o átomo D; e o quarto, é a sub lista (E (F G)), que tem como
seu segundo elemento a sub lista (F G).
Como LISP foi projetada no conceito de programação funcional, todas as
computações são realizadas por meio da aplicação de função a argumentos. A
sintaxe do LISP é, portanto, muito diferente de linguagens imperativas, como
C++ ou Java. Por exemplo, em Java, a sintaxe é uma mistura de inglês e álgebra,
ao passo que em LISP, a sintaxe é um modelo simplista, o código e os dados
dos programas têm exatamente a mesma forma: listas dentro de parênteses.
Considere mais uma vez a lista (A B C D). Quando interpretada como dados,
ela é uma lista de quatro elementos, mas se vista como código, é a aplicação
da função chamada A para os três parâmetros B, C e D.
A Figura 2 demonstra a representação interna de duas listas em LISP.
Figura 2. Representação interna de duas listas em LISP.
Fonte: Adaptada de Sebesta (2018).
Programação declarativa4
Veja a seguinte função de exemplo em LISP. O código a seguir define
uma função de predicado em LISP que recebe duas listas como argumentos
e retorna True, se as duas listas forem iguais, ou NIL (false) caso contrário.
(DEFUN equal _ lists (lis1 lis2)
(COND
((ATOM lis1) (EQ lis1 lis2))
((ATOM lis2) NIL)
((equal _ lists (CAR lis1) (CAR lis2))
(equal _ lists (CDR lis1) (CDR lis2)))
(T NIL)
)
)
Linguagem de programação Prolog
O Prolog é baseado em cláusulas de Horn (um subconjunto da lógica de primeira
ordem), e é provavelmente a linguagem mais famosa na família de programação
lógica. Foi um projeto colaborativo de Alain Colmerauer, Phillipe Roussel
(ambos da Universidade de Aix-Marselha) e Robert Kowalski (Universidade
de Edimburgo). Sua primeira versão apareceu, como Smalltalk e C, em 1972.
Seu nome é uma abreviatura de programmation en logique (francês para
programação em lógica).
Para Nicoletti (2003, p. 35), o Prolog tem sido muito influente nos domínios
das provas de teoremas, sistemas especialistas, processamento de linguagem
natural e no campo da inteligência artificial (notavelmente o IBM Watson2)
em geral. Além disso, influenciou de forma significativa o desenvolvimento
da linguagem de programação Erlang.
Para Sebesta (2018), o Prolog é uma linguagem de programação de alto
nível baseada em lógica formal. Ao contrário das linguagens de programação
tradicionais, baseadas na execução de sequências de comandos, o Prolog é
baseado na definição e na solução de fórmulas lógicas. Por vezes, é chamado
de linguagem declarativa ou baseada em regras, porque seus programas con-
sistem em uma lista de fatos e regras. É, também, amplamente utilizado para
aplicações de inteligência artificial, em particular para sistemas especialistas.
5Programação declarativa
O Prolog possui quatro blocos de construção:
� lógico or;
� lógico and;
� reescrita de termos;
� unificação.
Combinando esses quatro blocos, é possível executar qualquer computação.
O Prolog, assim como o SQL, tem dois aspectos principais, um para expressar
os dados e outro para consultá-los. As construções básicas da programação
lógica, termos e declarações são herdadas da lógica. Existem três declarações
básicas:
� fatos, que são afirmações fundamentais sobre o domínio do problema
(por exemplo, “Sócrates é um homem.”);
� regras, que são inferências sobre fatos no domínio (por exemplo, “Todos
os homens são mortais.”);
� consultas, que são perguntas sobre esse domínio (por exemplo,
“É Sócrates mortal?”).
Fatos e regras são armazenados em uma base de conhecimento que o
compilador Prolog transporta para uma forma mais eficiente para consulta.
Quando “fazemos” uma pergunta, o Prolog faz uma pesquisa exaustiva por
meio do banco de dados de fatos e regras até encontrar um resultado, usando
o backtracking internamente.
Aprenda pelo menos uma nova linguagem de programação a cada ano. Diferentes
linguagens resolvem os mesmos problemas de maneiras diferentes, ao aprender várias
abordagens, você amplia seu pensamento e evita “ficar preso” em uma mesma rotina.
Além disso, aprender linguagens de programação é muito mais fácil atualmente, pois
há muitos softwares disponíveis gratuitamente na Internet.
Programação declarativa6
A escolha de linguagens declarativas, seja do tipo lógica ou funcional,
é sempre uma questão ligada ao contexto da solução que se deseja atender.
Linguagens declarativas são de excelente aplicação em contextos mais abs-
tratos, como consultas a banco de dados e questões que envolvam áreas da
inteligência artificial.
Para conhecer os pilares e conceitos do paradigma de programação orientada a
objetos acesse o link a seguir.
https://qrgo.page.link/JBCZA
BOTELHO, L. M. Inteligência artificial: apontamentos para as aulas. Lisboa: Departamento
de Ciências e Tecnologias da Informação, Instituto Superior de Ciências do Trabalho
e da Empresa, 2015. 10 p. Disponível em: http://home.iscte-iul.pt/~luis/aulas/ia/Co-
nhecimento%20declarativo%20em%20programacao%20em%20logica.pdf. Acesso
em: 21 ago. 2019.
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2.
ed. Porto Alegre: AMGH, 2009. 630 p.
Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. PortoAlegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
7Programação declarativa
MILETTO, E. M.; BERTAGNOLLI, S. C. Desenvolvimento de software II: introdução ao de-
senvolvimento web com HTML, CSS, JavaScript e PHP. Porto Alegre: Bookman, 2014.
276 p. (Série Tekne; Eixo Informação e Comunicação).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
Programação declarativa8
DICA DO PROFESSOR
A programação funcional é uma maneira de pensar sobre a construção de software, criando
funções puras. As linguagens funcionais são declarativas, pois usam expressões e declarações,
em vez de execução de instruções. São, portanto, linguagens que apresentam características de
abstração e previsibilidade, entre outras vantagens.
Na Dica do Professor, você verá um pouco mais sobre as características da linguagem funcional
e por que ela se enquadra como um dos tipos de linguagem declarativa.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) As linguagens de programação declarativas têm como principal característica lógica
do programa estarem orientadas para o resultado a ser obtido e não para o modo
como será alcançado. Ou seja, têm foco no quê e não no como. Assinale a alternativa
que descreva outra característica também associada a esse paradigma:
A) Modelagem de entidades do mundo real.
B) Facilidade de aprendizagem.
C) Comandos e instruções passo a passo.
D) Facilidade de integração com outras linguagens.
E) Criação de códigos enxutos.
2)
As linguagens de programação declarativa, assim como linguagens em outros
paradigmas, são indicadas para programas em algumas áreas do conhecimento.
Assinale a alternativa que identifica as áreas do conhecimento em que mais se
aplicam as linguagens de programação declarativa:
A) Processamento de Imagem e Banco de Dados.
B) Sistemas Estruturados e Processamento de Imagem.
C) Jogos e Banco de Dados.
D) Inteligência Artificial e Banco de Dados.
E) Móbile e Sistemas Web.
3) As linguagens de programação lógica, como o Prolog, têm grande embasamento na
lógica matemática, fazendo uso de símbolos na declaração pela lógica de predicados.
Assinale a alternativa correta acerca de algumas características da programação
lógica:
A) Processamento simbólico e fácil modificação.
B) Processamento simbólico e soluções algorítmicas.
C) Difícil modificação e respostas parcialmente corretas.
D) Soluções heuríticas e soluções algorítmicas.
E) Estruturas de controle e de conhecimento integradas.
4) O paradigma de programação funcional é uma forma de programação declarativa,
criado explicitamente para dar suporte a uma abordagem funcional pura, para a
solução de problemas. Para atingir esse objetivo, são características desse paradigma:
A) Alta importância da ordem de execução dos passos.
B) Controle de fluxo, utilizando loops e condições.
C) Alterações no programa são mais complexas.
D) Foco em como controlar tarefas.
E) Foco em funções com objetos de primeira classe e coleção de dados.
5) As linguagens de programação por restrições são uma complementação ao padrão
lógico e se referem à implementação de restrições na relação entre variáveis,
especificando soluções e critérios a serem cumpridos, atuando sobre domínios. As
linguagens de programação por restrições atuam sobre alguns domínios. Assinale a
alternativa abaixo que apresenta alguns domínios onde esse tipo de linguagem atua:
A) Estrutural e condicional.
B) Matemático e funções.
C) Booleano e finito.
D) Estrutural e orientado a objetos.
E) Imperativo e funcional.
NA PRÁTICA
A linguagem LISP é um exemplo de linguagem declarativa funcional muito utilizada em
aplicações que necessitam resolver questões matemáticas mais complexas, como em um jogo de
xadrez.
O jogo de xadrez exige raciocínio lógico e capacidade de realizar cálculos probalísticos
matemáticos, por isso, a criação de um programa em LISP que utiliza os recursos da
programação declarativa é um bom exemplo de uso desse paradigma.
Confira, Na Prática, a criação de um programa em LISP básico que possibilita um jogo de
xadrez entre o usuário e o computador e compreenda como a linguagem declarativa se adapta a
esses casos.
Conteúdo interativo disponível na plataforma de ensino!
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Imperativo ou Declarativo?
Confira, neste artigo, uma comparação didática sobre as diferenças entre os Paradigmas
Declarativo e Imperativo.
Conteúdo interativo disponível na plataforma de ensino!
A linguagem SQL
Este artigo apresenta uma introdução sobre a linguagem declarativa SQL. Confira essa descrição
e por que essa linguagem se tornou a mais explícita do paradigma declarativo.
Conteúdo interativo disponível na plataforma de ensino!
Introdução à Linguagem de Programação PROLOG
Confira, no vídeo, uma breve apresentação sobre a linguagem declarativa PROLOG, uma das
primeiras linguagens de programação declarativa que surgiu.
Conteúdo interativo disponível na plataforma de ensino!
Programação imperativa
APRESENTAÇÃO
O imperativo é o mais antigo dos paradigmas da computação e se consagrou como o mais
utilizado e de maior sucesso, visto que a maioria das linguagens de programação implementam-
no, mesmo que também implementem outros paradigmas como o orientado a objetos ou o
estruturado, por exemplo. O paradigma imperativo alcançou sucesso também pelo fato de se
adaptar ao modelo clássico de Von Neumann, em que o programa e seus dados são alocados na
mesma memória, o que facilita o processamento das instruções pelo compilador.
Nesta Unidade de Aprendizagem, você irá conhecer o que é a programação imperativa, como
distinguir as linguagens de programação imperativa e exemplos de sua aplicação.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Explicar o que é a programação imperativa.•
Distinguir as linguagens de programação imperativa.•
Aplicar a programação imperativa.•
DESAFIO
O paradigma imperativo é o mais antigo dos paradigmas da computação e o que obteve, até
então, o maior sucesso. Esse sucesso pode ser relacionado à própria arquitetura de
processamento dos computadores. Conhecê-lo e saber como aplicá-lo é fundamental.
Veja a seguinte situação:
Você foi contratado como desenvolvedor em uma equipe de desenvolvimento para um novo
projeto. Nesse projeto, o seu desafio será construir um sistema responsável por automatizar as
rotinas de planejamento e controle da programação da linha de produção. As características do
ambiente exigem que o programa execute rotinas de reprogramação da linha de produção, sem
grande necessidade de interface gráfica, nem preocupações com integrações, por exemplo, e que
rode em computadores cujos recursos de hardware são poucos, como memória e CPU.
Então você sugere a implementação em uma determinada linguagem, após analisar as
características do software e os requisitos de ambiente.
a) Qual linguagem você sugere?
b) Como você utilizaria a programação imperativa por meio dessa linguagem para atender a esse
cenário? Lembre-se de justificar sua escolha.
INFOGRÁFICO
O paradigma de programação imperativo é o mais estabilizado e utilizado pela maioria das
linguagens de programação. Ele se baseia no modo de funcionamento do computador, ou seja, é
influenciado por sua arquitetura. Consequentemente, isso se reflete na execução sequencial
baseada em comandos e no armazenamento de dados alteráveis, conceitos que são baseados na
maneira pela qual computadores executam os programas em nível de linguagem de máquina. O
termo “imperare”, do Latim, significa “comandar”.O paradigma imperativo foi predominante nas linguagens de programação, pois estas são mais
fáceis de traduzir para uma forma adequada de execução na máquina.
No Infográfico a seguir, você irá conhecer os principais conceitos que caracterizam uma
linguagem de programação imperativa e as primeiras linguagens que implementaram esse
paradigma.
CONTEÚDO DO LIVRO
O paradigma de programação caracteriza-se por se basear no próprio funcionamento do
computador, que, por sua vez, baseia-se no modelo de Von Neumman. Essa característica é
perceptível no modo de instrução sequencial e alteração do estado de variáveis, conceitos
fundados na forma como os computadores executam programas em nível de linguagem de
máquina. Isso justifica certamente o grande sucesso desse paradigma e o grande número de
linguagens de programação que implementam suas características.
Na obra Paradigmas de programação, base teórica para essa Unidade de Aprendizagem, leia o
capítulo Programação Imperativa e conheça um pouco mais sobre o paradigma imperativo, as
principais características de linguagens de programação que implementam esse paradigma e
alguns exemplos de aplicação.
Boa Leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação imperativa
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Explicar o que é a programação imperativa.
� Distinguir as linguagens de programação imperativa.
� Aplicar a programação imperativa.
Introdução
O paradigma imperativo na computação tem em seu nome a semelhança
com o padrão imperativo das linguagens naturais que expressam ordens.
Portanto, linguagens de programação (LP), que implementam esse padrão,
são caracterizadas por programas construídos a partir de algoritmos
que expressam uma sequência de comandos a serem executados pelo
computador para alcançar determinado resultado.
O paradigma imperativo é o mais antigo dos paradigmas da com-
putação e o que obteve, até então, o maior sucesso. Esse sucesso
pode ser relacionado à própria arquitetura de processamento dos
computadores.
Neste capítulo, você entenderá do que se trata o paradigma im-
perativo, algumas das linguagens mais utilizadas e um pouco da sua
aplicação.
Paradigma imperativo
O paradigma de programação imperativo surgiu na década de 1940, quando
John von Neumann e colaboradores percebem que tanto um programa de
computador como seus dados poderiam compartilhar a memória principal.
Essa descoberta foi um conceito inovador, devido ao fato de que os primeiros
computadores armazenavam seus programas fora da memória. Com a pos-
sibilidade de armazenar um programa na memória, foi possível alcançar um
novo patamar de versatilidade e computação.
A arquitetura do modelo de von Neumann se tornou, então, a base do
conceito do paradigma de programação imperativa, na qual a memória da
máquina contém tanto as instruções do programa que está executando como
os valores dos dados (armazenamento dos dados). Além disso, no centro dessa
arquitetura, encontra-se outra característica clássica do paradigma imperativo:
alterar o valor de um local de memória e destruir o seu valor anterior, ou seja,
o conceito de atribuição.
Segundo Tucker e Noonan (2009, p. 277):
Já que elas surgiram do modelo de von Neumann-Eckert, todas as linguagens
imperativas incluem a atribuição como um elemento central. Além disso, elas
suportam declarações de variáveis, expressões, comandos condicionais, laços
e abstração procedural.
Em LP imperativas, as expressões são interpretadas conforme a recuperação
de valores correntes de variáveis por meio de nomes que referenciam seus
respectivos endereços na memória.
A Figura 1 ilustra o exemplo clássico da estrutura do modelo de von
Neumman e como programas em linguagens imperativas são executados
pelo computador.
Programação imperativa2
Figura 1. Arquitetura de von Neumann e o paradigma de LP imperativa.
Fonte: Linguagem... (2018, documento on-line).
Ainda utilizando como base a arquitetura de von Neumman, programas
construídos em linguagens imperativas tem seus comandos executados na
ordem em que aparecem na memória, embora os comandos condicionais e as
ramificações possam alterar um pouco esse fluxo de execução. No início, os
comandos de uma linguagem imperativa eram apenas abstrações simplifica-
das de instruções em máquinas de von Neumman, padrão que englobavam
comandos de atribuição, condicionais e ramificações.
Boa parte dos computadores mais populares nos últimos anos foi projetada com base
na arquitetura proposta por von Neumann. Nela, dados e programas são armazenados
na mesma memória. A unidade central de processamento (UCP), que executa realmente
as instruções, é separada da memória.
3Programação imperativa
Dessa forma, podemos sintetizar que a fundamentação da programação
imperativa se resume a três conceitos:
� Estado de uma máquina, relacionado aos valores de um conjunto de
variáveis.
� Expressões, compostas pela relação entre esses valores ou o resultado
de operações entre esses valores.
� Comandos de atribuição e controle, que manipulam esses estados das
variáveis.
Em outras palavras, um programa escrito em uma linguagem imperativa
é representado por um conjunto de dados que determinam o seu estado e, por
meio da manipulação desses dados (leitura, criação de expressões e geração
de novos valores), o seu estado vai sendo alterado até o resultado esperado
ser alcançado.
Linguagens de programação imperativas
Agora, você verá um pouco mais sobre as características que definem se uma
linguagem se enquadra no paradigma de programação imperativa e alguns
exemplos de linguagens imperativas. Além das características já comentadas
em relação à implementação de instruções e comandos que um programa em
linguagem imperativa especifica para que o computador alcance determinado
resultado, uma linguagem imperativa é classificada completa quanto a Turing
quando possibilita a implementação de qualquer algoritmo que possa ser
projetado (TUCKER; NOONAN, 2009).
Ser completa quanto a Turing é uma característica que permite mensurar se
uma linguagem consegue implementar qualquer situação, incluindo situações
comuns que envolvam:
� estruturas de controle;
� entrada e saída de dados;
� manipulação de exceções e erros;
� abstração procedural;
� expressões e atribuição;
� suporte de bibliotecas para estrutura de dados.
Programação imperativa4
Para definir melhor este conceito, vamos analisar a implementação dessas
características do ponto de vista de duas linguagens imperativas, a linguagem
C e a linguagem Ada. A linguagem C foi projetada inicialmente para ser
implementada no sistema operacional UNIX, nos laboratórios Bell, por Ken
Thompson e Dennis Ritchie, que participavam ativamente do desenvolvimento
de um avançado sistema operacional que, ao contrário dos sistemas operacionais
criados, estava sendo escrito em programming language one (PL/I) em vez
de assembly (OKUYAMA; MILETTO; NICOLAO, 2014).
Após o laboratório Bell desistir do projeto do sistema operacional, Thomp-
son e Ritchie continuaram o desenvolvimento de um sistema de documentação,
que seria independente de máquina e possibilitava a execução em minicompu-
tadores baratos do final de 1960, nascia assim o sistema operacional UNIX.
A linguagem C foi utilizada na construção desse sistema operacional, incial-
mente baseada na linguagem basic combined programming language (BCPL)
que não possuía tipo (OKUYAMA; MILETTO; NICOLAO, 2014).
A partir disso, a linguagem C foi amplamente utilizada, principalmente
em ambientes acadêmicos, tendo, inclusive, impacto no surgimento de inú-
meras outras linguagens conhecidas atualmente, como Java, Python e C++
(PINHEIRO, 2012).
A linguagem C possui comandos de atribuição, sequência e os condicionais
if e switch, laços while, for e do e chamadas a funções. Com relação à estrutura
de dados, a linguagem C permite trabalhar com matrizes,ponteiros, estrutu-
ras (registros) e tipos de dados de união. Como uma linguagem imperativa,
o C não possui:
� iteradores;
� manipulação de exceções;
� sobrecarga;
� genéricos.
Veja um exemplo de código em C que define uma estrutura com nome, ano
de matrícula, curso e média de entrada de um aluno e, logo após, implementa
uma função de receber como parâmetro um apontador para uma estrutura do
tipo definido, criando dinamicamente uma estrutura. Para a nova estrutura,
devem ser copiados os dados da estrutura recebida. A função retorna o apon-
tador para a nova estrutura ou NULL, caso não consiga reservar memória.
5Programação imperativa
typedef struct aluno {
char nome[40];
int ano;
char curso[40];
float media;
} aluno;
aluno * copia _ aluno( aluno * a)
{
aluno *t;
t=(aluno *)malloc(sizeof(aluno));
if (t==NULL)
return t;
*t = *a;
/* ou:
strcpy(t->nome,a->nome);
t->ano = a->ano;
strcpy(t->curso,a->curso);
t->media = a->media;
*/
return t;
}
Outro bom exemplo de linguagem imperativa, é a linguagem Ada. Ela foi
desenvolvida no final da década de 1970 pelo departamento de defesa norte-
-americano para ser usada em grandes sistemas de controle e comando e em
sistemas embarcados em tempo real. Caracteriza-se por ser uma LP imperativa
de alto nível e baseada em Pascal.
Seu principal projetista foi o francês Jean Ichbiah. A linguagem foi pa-
dronizada pela American National Standards Institute (ANSI) em 1983 e,
em 1985, pela International Organization for Standardization (ISO). Um fato
curioso acerca da linguagem Ada é que, em 1995, a ISO padronizou uma
versão melhorada chamada de Ada 95, que se tornou a primeira LP orientada
a objeto (OO) padronizada internacionalmente (TUCKER; NOONAN, 2009).
Programação imperativa6
A estrutura básica de um programa em Ada é a seguinte:
-- Declarações de bibliotecas
Procedures nome _ do _ programa is
-- Declarações de variáveis
begin
-- Corpo do programa
end nome _ do _ programa;
Pela estrutura demonstrada, você pode perceber as características do
paradigma imperativo na linguagem. Vamos analisar o seguinte:
� Linguagens imperativas permitem a troca de valor de variáveis no
trecho do código do programa, logo após a sua criação é designado um
espaço para a declaração das variáveis.
� Linguagens imperativas permitem que as variáveis sejam manipuladas
e as instruções e os comandos sejam repassados para o computador,
explicando como fazer para chegar a um determinado resultado, logo
após o comando begin é necessário especificar o que o programa
deverá fazer.
Desenvolvendo e aplicando programação
imperativa
Para ajudar a elucidar o conceito de programação imperativa, analise o código
em Ada, apresentado na Figura 2. Esse exemplo demonstra a aplicação do
paradigma imperativo por meio da criação de um algoritmo que escreve a
tabuada.
7Programação imperativa
Figura 2. Algoritmo em Ada que escreve a tabuada.
Fonte: Leal (2012, documento on-line).
No algoritmo apresentado na Figura 2, você pode perceber que a linguagem
Ada possibilita outros recursos de linguagens imperativas, como os comandos
interativos, nesse caso representados pelo comando FOR.
Segundo Tucker e Noonan (2009), as linguagens com a maior influência
sobre Ada foram Algol e Pascal. Exemplos dessa influência abundam: desde
o uso do símbolo := para atribuição até o uso de begin-end para blocos.
Sintaticamente, as duas maiores diferenças dessas linguagens predecessoras
foram o uso de símbolos de término únicos para estruturas compostas; e o
uso do ponto e vírgula como um símbolo de término de comando, em vez de
um separador de comandos.
Podemos também perceber que a sintaxe da linguagem Ada exige bem mais
comandos do que a linguagem C. O exemplo da escrita da média demanda
bem mais comandos em Ada do que seria necessário na linguagem C.
Programação imperativa8
Vamos, agora, comparar por meio do exemplo demonstrado na Figura 3,
a sintaxe de um algoritmo em linguagem C, que consiste em ler números, um
de cada vez, e, então, contar e somar. Por último, o algoritmo verifica se o
número analisado é o novo número mínimo ou máximo da lista. Perceba que
a sintaxe usa comandos imperativos e uso de variáveis.
Figura 3. Algoritmo em C que faz contagem, soma e análise de números em sequência.
Fonte: Tucker e Noonan (2009, p. 288).
O programa usa uma declaração de atribuição múltipla para inicializar sum
e ct e, posteriormente, min e max. Atribuições condicionais são usadas para
atualizar min e max. A entrada e a saída que utilizam códigos de formatos
também são utilizadas.
Para finalizar, analise um exemplo em outra linguagem imperativa, o Perl.
Segundo Tucker e Noonan (2009, p. 296), “Perl é uma linguagem de scripting
amplamente usada, que é uma linguagem de alto nível interpretada em tempo
de execução em vez de compilada em linguagem de máquina”.
9Programação imperativa
O exemplo da Figura 4 é um script em Perl que envia as notas de alunos
por e-mail; esse é um bom exemplo de casos em que linguagem de scripting
imperativa Perl é empregada. Perceba, também a utilização das características
imperativas no código.
Figura 4. Script em Perl que envia por e-mail as notas de alunos.
Fonte: Tucker e Noonan (2009, p. 304).
Em todos os exemplos, é perceptível, apesar das diferenças e aplicações
das linguagens, que todas seguem os princípios do paradigma imperativo,
deixando clara a sua importância para a computação.
Programação imperativa10
Veja, no link a seguir, alguns vídeos nos quais são feitas comparações entre os para-
digmas imperativo, funcional e OO.
https://qrgo.page.link/jtDar
LEAL, C. Linguagem de Programação Ada. Mostre ao Mundo, Campinas, 19 out. 2012.
Disponível em: http://www.mostreaomundo.com.br/2012/10/linguagem-de-progra-
macao-ada.html. Acesso em: 28 ago. 2019.
LINGUAGEM de programação: classificações. Universidade da Tecnologia, [S. l.], 16 fev.
2018. Disponível em: https://universidadedatecnologia.com.br/linguagem-de-progra-
macao-classificacoes/. Acesso em: 28 ago. 2019.
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas.
2. ed. Porto Alegre: AMGH, 2009. 630 p.
Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
MILETTO, E. M.; BERTAGNOLLI, S. C. Desenvolvimento de software II: introdução ao de-
senvolvimento web com HTML, CSS, JavaScript e PHP. Porto Alegre: Bookman, 2014.
276 p. (Série Tekne; Eixo Informação e Comunicação).
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
11Programação imperativa
DICA DO PROFESSOR
Certamente você já desenvolveu, em alguma linguagem de programação que implementou, o
paradigma imperativo, ou, então, se ainda não implementou, certamente
irá implementar. Apesar de seu grande sucesso e das características que o tornam um paradigma
estável, existem vantagens e desvantagens que todo profissional precisa conhecer.
Na Dica do Professor de hoje, conheça as principais características do paradigma imperativo e
suas principais vantagens e desvantagens.
Conteúdo interativo disponível na plataforma de ensino!EXERCÍCIOS
1) O paradigma de programação imperativa é largamente caracterizado pelo fato de
seus programas expressarem instruções e comandos que o computador deve executar
para alcançar os objetivos. Outra característica importante do paradigma de
programção imperativa é:
A) Mutação de estado (alterar os valores das variáveis).
B) Costuma expressar o código principalmente por meio de funções.
C) Implementa recursos de herança e polimorfismo entre as classes.
D) As expressões são compostas por símbolos e letras.
E) Caracteriza-se pela implementação de subprogramas ou modularização de programas.
As linguagens de programação imperativa podem ser classificadas como completas 2)
quanto a Turing. Analise as questões e assinale a que representa uma síntese do que
significa ser completa quanto a Turing.
A) Possibilitar a implementação de recursos de reutilização de código.
B) Apresentar sintaxe semelhante a linguagens de baixo nível.
C) Apresentar recursos que permitem expressar qualquer algoritmo computacional.
D) Possibilitar que os dados de um programa fiquem fora da memória do computador.
E) Permitir tratar todas as exceções de código em um algoritmo.
3) As linguagens de programação imperativa são também chamadas de linguagens
procedurais devido ao fato de permitirem uma certa estruturação do código
construído. Acerca desse conceito, assinale a alternativa que apresenta uma
desvantagem dessa característica:
A) Falta de recursos de implementação de código recursivo.
B) Dificuldade em legibilidade do código.
C) Falta de recursos de comandos interativos.
D) Falta de flexibilidade dado o caráter sequencial das instruções.
E) Dificuldade de disponibilidade de linguagens de programação no mercado.
A programação em linguagem imperativa se caracteriza por expressar a chegada a
um resultado e não como. Analise o código abaixo, acerca de um o trecho do código
4)
de um programa em linguagem C, e assinale a alternativa correta sobre a
característica do paradigma imperativo que é possível perceber.
function join(array) { var text = ""; for (var i = 0; i < array.length; i++) {
text += array[i];
}
return text;
}
A) Uso de função.
B) Instruções explícitas.
C) Comando incremental.
D) Reuso código.
E) Código enxuto.
5) Uma linguagem de programação pode dar suporte a mais do que um só paradigma
de programação. Nesse contexto, analise as alternativas a seguir e assinale a que
apresenta as características que justifiquem que uma linguagem forneça suporte à
implementação do paradigma imperativo.
A) Funções, estruturas de controle e abstração procedimentos.
B) Variáveis, implementação lógica e abstração de procedimentos.
C) Variáveis, atribuição e execução sequencial de procedimentos.
D) Alto nível de abstração e implementação sequencial de instruções.
E) Variáveis, estruturas de controle e alta abstração.
NA PRÁTICA
A linguagem de programação PASCAL é um bom exemplo de linguagem imperativa, muito
utilizada, na década de 1990, em aplicações comerciais e também em ambientes acadêmicos,
sendo inclusive, em muitos casos, juntamente com o C, a linguagem de introdução aos
estudantes ao ambiente de programação.
A utilização da linguagem PASCAL para soluções que necessitam de instruções sequenciais
para se chegar a um determinado resultado, ou seja, soluções que necessitam de uma
implementação em linguagem imperativa, é uma boa alternativa. Veja, Na Prática, um exemplo
de como ocorre a criação de um programa em PASCAL que identifica se um número informado
é um número primo.
Conteúdo interativo disponível na plataforma de ensino!
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Diferença entre as programações Orientação-objetos, Imperativa e Funcional
Neste site, leia este excelente material que faz um comparativo da programação imperativa com
outros paradigmas de programação.
Conteúdo interativo disponível na plataforma de ensino!
Introdução à lógica de programação imperativa
Para saber mais, assista a esse vídeo, que mostra uma introdução à lógica de programação
imperativa.
Conteúdo interativo disponível na plataforma de ensino!
Introdução a Lógica de programação Imperativa
Conteúdo interativo disponível na plataforma de ensino!
Programação estruturada
APRESENTAÇÃO
A programação estruturada é um paradigma de programação cujo princípio é a construção de
códigos legíveis, de fácil entendimento e manutenção. É um paradigma independente de
linguagem de programação que fez grande sucesso entre os desenvolvedores por estabelecer
uma disciplina rígida de padronização e construção de programas.
Nesta Unidade de Aprendizagem, você vai compreender os princípios e fundamentos da
programação estruturada, vai ainda conhecer algumas linguagens de programação que
implementam esse paradigma e a sua aplicação em casos reais.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Reconhecer a programação estruturada.•
Descrever as linguagens de programação estruturada.•
Aplicar a programação estruturada.•
DESAFIO
As linguagens de programação estruturada surgiram como uma nova proposta às antigas
linguagens, as quais demandavam desvio de fluxo em um código com a utilização dos
comandos GOTO, constituindo casos em que o fluxo às vezes tornava complexa a análise de
código. Esse tipo de comando era muito utilizado para resolver situações de desvio de fluxo em
linguagens como BASIC, por exemplo.
Assim, considere a seguinte situação:
Você trabalha em uma equipe de desenvolvimento e recebeu da sua gerência o desafio de
reescrever um sistema atual em BASIC para a linguagem C. Ao analisar o código atual, você
percebe problemas característicos da implementação que justificam a migração para uma nova
linguagem, uma vez que eles tornam o código difícil de manter e interpretar. A seguir, veja o
código:
Considerando a situação apresentada:
a) Identifique problemas no código.
b) Justifique como a implementação estruturada em C conseguiria solucionar esses problemas.
INFOGRÁFICO
Nos anos 70, em decorrência da crise do software das décadas antecessoras, surgiram avanços
na linguagem de programação, como a programação estruturada. A programação estruturada,
portanto, foi a consequência de melhorias no padrão de desenvolvimento de software.
A seguir, no Infográfico, veja, de forma sintetizada, alguns eventos de melhoria nas linguagens
que surgiram nessa época e que estão relacionados com a programação estruturada.
CONTEÚDO DO LIVRO
A crise do software, cujo ápice foi na década de 60, fez com que a indústria do ramo
desenvolvesse novas formas de construção de software voltadas a uma fácil manutenção e
entendimento dos programas de computadores. Neste cenário, surgem novas formas de se
estruturar o código e outras linguagens para suportar novas estruturas de programação. Assim,
surgem os conceitos que formariam os fundamentos do paradigma de programação estruturada.
Leia o capítulo Programação estruturada, da obra Paradigmas da Programação, e aprenda o
significado de programação estruturada, vendo também algumas linguagens percursoras
do paradigma e como são implementados programas com os conceitos de programação
estruturada.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação estruturada
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Reconhecer a programação estruturada.
� Descrever as linguagens de programação estruturada.
� Aplicar a programação estruturada.
Introdução
O paradigma de programação estruturada se refere a construção de
programas que permitem uma clareza lógica na implementação de seu
código. Esse paradigma, implementado por muitas linguagens, como
Pascal, C, Fortran e Cobol, foi muito utilizado em programas nas décadas
de 1970 e 1980.
A programação estruturada temcomo princípio a estruturação do
código por intermédio de apenas três estruturas de controle básicas.
Neste capítulo, você entenderá melhor os conceitos da programação
estruturada, a sintaxe de algumas das linguagens que utilizam esse tipo
de programação e a sua aplicação em alguns programas.
Programação estruturada
Para entender a motivação que originou a programação estruturada, é funda-
mental lembrar que tudo começou com a famosa crise do software na década de
1960. Nessa época, Edsger W. Dijkstra, por meio do seu artigo A Case against
the GO TO Statement, criticou o uso excessivo desse comando na programação.
O comando GO TO, amplamente utilizado pelas linguagens de programação da
época, trata-se de uma estrutura de controle para permitir saltos de instruções.
Sua ampla utilização pelos programadores gerava um número considerável de
programas praticamente impossíveis de serem entendidos, e a consequência
disso era a dificuldade de manutenção dos programas.
Essa declaração foi originalmente essencial para a programação no Basic,
pois os intérpretes mais antigos apenas permitiam que as instruções if fossem
executadas em uma linha e não tinham manipulação mais avançada dos loops
for ou while. Nas versões modernas do Basic, você verá o GOTO, grafado
como uma única palavra, usado apenas para retornar ao topo de um loop
principal (SEBESTA, 2018, p. 267). No exemplo a seguir, você pode observar
a implementação do comando GOTO no Basic, que fica lendo um valor na tela
e retornando à instrução para ler o novo número.
10 READ R
20 PRINT "R ="; R;
30 A = 3.14*R^2
40 PRINT "AREA ="; A
50 GOTO 10
Segundo Tucker e Noonan (2009, p. 168), “A controvérsia do comando
Go To começou com uma nova carta de Dijkstra, desta vez para o editor da
Communications of the ACM, intitulada Go To Statement Considered Harmful
(Declaração Go To considerada prejudicial). Com essa carta, a revolução da
programação estruturada estava lançada.
A partir de então, inicia-se uma revolução na forma de construção de
códigos para programas, que seria a base para o surgimento da programação
estruturada. De modo geral, esse paradigma de programação, com o objetivo
de corrigir os problemas citados, embasava o projeto de programas com prin-
cípios básicos por meio da utilização de apenas três estruturas de controle:
� Sequência — implementa os passos de processamento necessários
para a descrição de qualquer programa, por exemplo, um segmento
de código em que é enviado o comando ''faça tarefa 1'' e,
logo após, o comando ''faça tarefa 2'', pode ser representado
com a sequência de dois retângulos, ou em um pseudocódigo que seria
denotado pela expressão das duas tarefas uma após a outra.
� Seleção — possibilita que o fluxo de processamento seja selecionado
com base em sentenças lógicas, para isso são usadas duas formas de
condicional; a primeira seria o uso da condicional if then, e a
segunda, switch.
� Iteração — possibilita que segmentos do programa tenham a sua exe-
cução repetida até que uma determinada cláusula seja satisfeita. São
implementados por comandos while ou for, por exemplo.
Programação estruturada2
Na Figura 1 são demonstrados um exemplo de cada condicional de seleção.
Figura 1. Exemplo de condicionais if e switch.
Fonte: Monteiro (2018, documento on-line).
Outra razão importante para o início do movimento pela programação
estruturada foi a mudança no custo maior da computação de hardware para
de software, o que, consequentemente, exigia uma maior preocupação com a
construção e a manutenção de programas de computador (SEBESTA, 2018,
p. 40).
De forma geral, a programação estruturada foi um sucesso e os objetivos
foram alcançados. Os programadores abandonaram o uso irrestrito do comando
Go To e passaram a utilizar as construções em condições de laços e condições,
tanto que é raro encontrar o uso do comando Go To, apesar de ele ainda ser
utilizado em algumas poucas linguagens de programação. A evolução na pro-
gramação e o surgimento de novos paradigmas também tiveram uma grande
influência nos princípios básicos que originaram o paradigma da programação
estruturada. Muitas linguagens implementaram seus conceitos, mas algumas
tiveram maior influência na divulgação deles.
O desenvolvimento das linguagens C, Fortran 77 e Pascal no final da década
de 1960 estimularam o sucesso da programação estruturada. Diferentemente
de Fortran 66, essas linguagens permitiam o uso de laços e condicionais,
incluindo os laços com teste no início e teste no final do bloco de execução
laços for, comandos if-then-else e comandos switch/case, junto
ao comando composto que permitia o alinhamento dessas construções. C
também incluiu formas restritas de comandos Go To, englobando os comandos
return, break e continue.
3Programação estruturada
A seguir, você verá como as linguagens Fortran e Pascal implementam os
conceitos da programação estruturada e como foram fundamentais na ampla
divulgação e implementação do seu paradigma pelos desenvolvedores ao longo
da evolução da programação.
Linguagens de programação estruturadas
Agora que você já viu o que significa o paradigma de programação estruturada,
vamos explicar um pouco sobre as linguagens Fortran 77 e Pascal, conside-
radas, juntamente a linguagem C, como as linguagens-chave no processo de
implantação do conceito de programação estruturada.
Fortran surgiu como linguagem de programação de propósito geral, mas
foi muito utilizada em aplicações na área de engenharia. Sua primeira versão
foi em 1957, mas sem dúvida a versão mais utilizada é a 77, que implementa
os conceitos de programação estruturada (FARRER et al., 1992, p. 35).
A grande inovação foi que muitos compiladores Fortran 77 admitem sub-
conjuntos de comandos, isto é, aceitam extensões fora do padrão estabelecido
pelo American National Standards Institute (ANSI). Um programa em Fortran
77 básico é composto por uma sequência de linhas de texto que devem obe-
decer a uma determinada sintaxe para ser reconhecido como programa em
Fortran válido. A Figura 2 mostra um exemplo de um programa em Fortran
simplificado.
Figura 2. Exemplo de programa em Fortran.
Fonte: Farrer et al. (1992, p. 45).
Programação estruturada4
Segundo Farrer et al. (1992, p. 35) um programa em Fortran 77 deve
seguir algumas regras e restrições para a escrita de seu código fonte, ou seja,
podemos verificar regras que obedecem aos princípios e conceitos propostos
pela programação estruturada. Para que uma linguagem de programação seja
considerada estruturada é importante que, além do conceito de sequência,
também sejam implementadas as condicionais e comandos interativos. Em
Fortran 77, a estrutura condicional é alcançada pela instrução if-else. É
muito comum o uso da instrução if em Fortran, podendo ser empregada
de formas diferentes. O comando executável if (expressão lógica) deve ser
escrito em uma linha; no exemplo a seguir ela determina o valor absoluto de x:
if (x .LT. 0 ) x = -x
Se mais de um comando tiver de ser escrito dentro de if, então a seguinte
sintaxe será adotada:
if (expressão lógica) then
comandos
endif
Sendo assim, a estrutura geral de uma condicional if tem o seguinte
aspecto:
if (expressão lógica) then
comandos
elseif (expressão lógica) then
comandos
:
:
else
comandos
end if
Com relação a comandos interativos, o Fortran 77 tem apenas uma forma
de construção de loop, chamada do-loop. O do-loop corresponde ao que é
conhecido como for-loop em outras linguagens.
5Programação estruturada
A forma geral do comando do-loop é a seguinte:
do label var = expr1, expr2, expr3
comandos
label continue
onde:
var é uma variável do tipo integer (geralmente chamada de índice do loop);
expr1 especifica o valor inicial de var;
expr2 é o limite terminal do-loop;
expr3 é o incremento ou passo do-loop.
A variável do comando do-loop nunca deve ser modificada por outro comando dentro
do loop, pois isso causaria uma grande confusão. Muitos compiladoresFortran 77
permitem que do-loops sejam encerrados com o comando enddo. A vantagem é que o
comando label pode então ser omitido. A construção do loop com enddo é largamente
usada, mas não é um componente do Fortran 77 ANSI.
A linguagem C foi outra linguagem que teve importante papel na divulgação
da programação estruturada. Foi projetada inicialmente para ser implemen-
tada no sistema operacional UNIX nos laboratórios Bell, por Ken Thompson
e Dennis Ritchie, que participavam ativamente do desenvolvimento de um
avançado sistema operacional e que, ao contrário dos sistemas operacionais
criados, estava sendo escrito em Programming Language One (PL/I), em vez
de Assembly (OKUYAMA; MILETTO; NICOLAO, 2014, p. 78).
Após o laboratório Bell desistir do projeto do sistema operacional, Thomp-
som e Ritchie continuaram o desenvolvimento de um sistema de documentação,
que seria independente de máquina e possibilitava a execução em minicompu-
tadores baratos do final de 1960. Nascia, assim, o sistema operacional UNIX.
A linguagem C foi utilizada na construção desse sistema operacional, incial-
mente baseada na linguagem Basic Combined Programming Language (BCPL),
que não possuía tipo (OKUYAMA; MILETTO; NICOLAO, 2014, p. 79).
Programação estruturada6
A partir disso, a linguagem C foi muito utilizada, principalmente em
ambientes acadêmicos, tendo, inclusive, impacto no surgimento de inúme-
ras outras linguagens conhecidas atualmente, como Java, Python e C++
(PINHEIRO, 2012, p. 68).
A Common Business Oriented Language (Cobol) é uma linguagem de
programação que foi amplamente utilizada em organizações nas décadas
de 1970 e 1980. Outra linguagem de programação que teve importância na
disseminação do paradigma de programação estruturada foi a linguagem
Pascal, desenvolvida entre 1968 e 1970 por Nicklaus Wirth, da Universidade de
Zurique, na Suíça. Pascal tem grande relevância na programação estruturada,
porque um de seus objetivos era justamente segundo Farrer et al. (1999, p. 35)
“desenvolver uma linguagem de programação disciplinada de alto nível para
ensinar programação estruturada. Esta linguagem foi batizada com o nome
de Pascal, em homenagem a Blaise Pascal, filósofo e matemático francês que
viveu entre 1623 e 1662”.
Pascal obteve uma grande adesão, principalmente na comunidade acadê-
mica, sendo utilizada como linguagem de apresentação ao desenvolvimento
de programas por universidades nas décadas seguintes.
Todo programa construído em Pascal é basicamente subdividido em três
partes distintas, conforme detalhado a seguir.
� Cabeçalho do programa: é a área do código utilizada para se fazer a
identificação do programa, é atribuído pela instrução program seguido
de um nome, por exemplo, program CALCULA_AREA.
� Área de declarações: é utilizada para validar o uso de qualquer tipo
de identificador que não seja pré-definido, estando subdividida em
sete subáreas: uses, label, const, type, var, procedure e
function, por exemplo, A, B, C: integer.
� Corpo do programa: é o local em que o programa propriamente está
escrito, tem início com a instrução begin e é finalizado pela instrução
end, seguida do símbolo ponto (.). O uso dessas instruções caracteriza
o que chamamos de bloco.
7Programação estruturada
A Figura 3 mostra um exemplo de programa em Pascal.
Figura 3. Exemplo de programa em Pascal.
Fonte: Farrer et al. (1999, p. 41).
Pascal trabalha com estruturas condicionais representadas pelo comando
if, que tem por finalidade tomar uma decisão e desviar o fluxo de processa-
mento com base em uma sentença lógica.
if (x > 10) then
writeln("O valor da variável X é 10");
As estruturas de repetição em Pascal são implementadas pelos comandos
for, while e repeat, que tem por objetivo repetir a execução de um
bloco de instruções enquanto uma sentença for válida. Veja um exemplo de
estrutura for em Pascal:
for variavel := <início> to/downto <fim> do
begin
instrução1;
instrução2;
instrução3;
end;
Programação estruturada8
E, agora, um exemplo de estrutura while em Pascal:
while <condição> do
begin
<instruções para condição verdadeira>;
end;
E uma estrutura repeat em Pascal:
repeat
<comando1>;
<comando2>;
<comando3>;
until <condição>;
A seguir, analisaremos alguns exemplos da aplicação da programação
estruturada em algoritmos para fixar o entendimento.
Desenvolvendo e aplicando programação
estruturada
Para ajudar a elucidar o conceito de programação estruturada, vamos come-
çar analisando o código em Pascal, apresentado na Figura 4. Esse exemplo
demonstra a criação de um programa que solicita um número e, em seguida,
escreve uma tabuada de multiplicação desse número, caso for digitado o
número 0, o programa é finalizado.
9Programação estruturada
Figura 4. Algoritmo em Pascal que escreve a multiplicação de um número.
Fonte: Farrer et al. (1999, p. 97).
No código apresentado, você pode perceber a utilização dos comandos
sequenciais em Pascal, nos quais o código comanda ao compilador que digite
o número por meio do comando (write) e, depois, leia o número digitado
pelo comando (read).
É possível identificar também o uso de estrutura de repetição por meio do
comando repeat, nesse código são usadas estruturas de repetição aninhadas,
pois dentro da estrutura de repetição repeat existe uma segunda estrutura
de repetição while (FARRER et al., 1999, p. 95).
Vamos, agora, comparar por meio do exemplo demonstrado pela Figura 5,
a sintaxe de um algoritmo em linguagem C, que consiste em ler um número e
imprimir a sua tabuada, assim como no exemplo anterior, em Pascal. É possível
perceber as características da programação estruturada como a estrutura de
repetição while.
Programação estruturada10
Figura 5. Algoritmo em C que escreve a multiplicação de um número.
Fonte: Cunha (2012, documento on-line).
A seguir, vamos analisar o trecho de um código de um programa escrito
em Cobol 74. A Figura 6 ilustra o trecho do código em Cobol demonstrando,
como nos exemplos em C e Pascal, como fazer a tabuada de um número.
11Programação estruturada
Figura 6. Algoritmo em Cobol que escreve a multiplicação de um número.
Fonte: Danflits (2010, documento on-line).
Neste caso, também é podemos verificar o uso de estruturas condicionais,
ou seja, o paradigma de programação estruturada alcançou seu objetivo de
estruturar e organizar o código dos programas de computador.
Programação estruturada12
CUNHA, R. S. Tabuada da Multiplicação. iMasters, São Paulo, 27 mar. 2012. Disponível em:
https://forum.imasters.com.br/topic/460715-tabuada-de-multiplica%C3%A7%C3%A3o/.
Acesso em: 4 set. 2019.
DANFITS. Código Programa de Tabuada. Cobol — Códigos e Comentários, [S. l.], 28 jul.
2010. Disponível em: http://cobolflits.blogspot.com/2010/07/codigo-programa-de-
-tabuada.html. Acesso em: 4 set. 2019.
FARRER, H. et al. Fortran estruturado: Fortran 77. Rio de Janeiro: Guanabara Koogan,
1992. 194 p. (Programação Estruturada de Computadores).
FARRER, H. et al. Pascal estruturado: Turbo Pascal. 3. ed. Rio de Janeiro: LTC, 1999. 279 p.
(Programação Estruturada de Computadores).
MONTEIRO, L. P. Linguagem de programação: classificações. Universidade da Tecnolo-
gia, São Paulo, 16 fev. 2018. Disponível em: https://universidadedatecnologia.com.br/
linguagem-de-programacao-classificacoes/. Acesso em: 4 set. 2019.
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas.
2. ed. Porto Alegre: AMGH, 2009. 630 p.
Leituras recomendadas
DIJKSTRA, E. W. A Case against the GO TO Statement. Department of Computer Science–
University of Texas, Austin, 2011. Disponível em: http://www.cs.utexas.edu/users/EWD/
transcriptions/EWD02xx/EWD215.html. Acesso em: 4 set. 2019.
DIJKSTRA, E. W. Go To Statement Considered Harmful. Communications of the ACM, [S.
l.], v. 11, n. 3, p. 147–148, Mar. 1968. Disponível em: https://homepages.cwi.nl/~storm/
teaching/reader/Dijkstra68.pdf. Acesso em: 4 set. 2019.
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
13Programação estruturada
DICA DO PROFESSOR
A utilização de fluxogramas como técnica para esboço de linha de pensamento ou de raciocínio
é muito bem-vinda em diversas áreas do conhecimento. A situação não seria diferente na
computação, principalmente se as ideias forem organizadas de forma estruturada para a
construção de uma lógica.
A seguir, na Dica do Professor, aprenda sobre a construção de algoritmos estruturados e a
utilização de fluxogramas.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) A programação estruturada propõe uma disciplina para construção de códigos de
programas com o objetivo de permitir, entre outros fatores, uma fácil manutenção
dos programas. Esse paradigma surgiu no início da década de 70.
Acerca dos eventos que motivaram o surgimento da programação estruturada,
assinale a alternativa correta:
A) Permitir a introdução de novas linguagens de programação no mercado.
B) O sucesso e constante crescimento do mercado de softwares.
C) A crise do software e o uso excessivo de comandos GOTO nos códigos.
D) A normalização dos paradigmas de programação pela ANSI.
E) A necessidade do meio acadêmico em produzir códigos estruturados.
2) O princípio básico de programação estruturada é que um programa é composto por
blocos elementares de código que se interligam por intermédio de três mecanismos
básicos.
Assinale a alternativa correta quanto a estes três mecanismos:
A) Sequência, Seleção e Iteração.
B) Seleção, Variáveis e Identação.
C) Propriedades, Métodos e Seleção.
D) Sequência, Procedimento e Iteração.
E) Métodos, Seleção e Variáveis.
3) Na programação estruturada é fundamental a elaboração de algoritmos e, para
expressá-los, algumas formas de representação são usadas.
Assinale a alternativa correta sobre as formas de representação utilizadas para
algoritmos em programação estruturada:
A) Pseudocódigo, Linguagem Máquina e Prototipação.
B) Fluxogramas, Prototipação e Linguagem Natural.
C) Linguagem Natural, Prototipação e Pseudocódigo.
D) Linguagem Natural, Fluxogramas e Pseudocódigo.
E) Prototipação, Linguagem Máquina e Fluxogramas.
4) Uma das características da linguagem de programação estruturada são as estruturas
em sequência. Conforme tal característica, as instruções dos programas são
executadas sequencialmente de cima para baixo, linha a linha.
Com base nessa característica, assinale a alternativa correta quanto ao seu benefício
na estruturação de código:
A) Facilidade de processamento das instruções pelo compilador.
B) Facilidade em gerar controle e desvio na execução do código.
C) Facilidade em gerar uma documentação do código.
D) Facilidade de alocação de memória pois a medida que uma instrução é executada desaloca.
E) Facilidade em compreender o fluxo de execução de um Programa.
5) Uma das características da programação estruturada é a utilização de estruturas de
repetição, representada na maioria das linguagens estruturadas por comandos FOR e
While.
Assinale a alternativa correta quanto a uma das principais vantagens que essa
estrutura proporciona:
A) Maior performance do processamento das instruções.
B) Criação de blocos de execução de comandos GOTO.
C) Execução de blocos de instruções várias vezes.
D) Nova forma de escrever comandos condicionais.
E) Criação de funções repetitivas reduzindo código.
NA PRÁTICA
A linguagem COBOL é um exemplo de linguagem de programação estruturada que obteve
sucesso no mercado e, inclusive, é utilizada atualmente, principalmente em instituições
financeiras. Ela surgiu em 1959, mas somente em 1972 teve uma grande evolução, passando a
permitir estruturas de controle e repetição e se tornando, assim, uma das mais importantes
linguagens de programação estruturada.
A seguir, no Na Prática, veja a criação de um programa em COBOL para realizar as operações
básicas de manutenção de cadastro de clientes e verificar como estruturas sequenciais,
condicionais e de repetição são aplicadas nessa linguagem.
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Conhecendo a Programação Estruturada
Veja a seguir um resumo dos conceitos e da história da Programação Estruturada.
Conteúdo interativo disponível na plataforma de ensino!
Programação Estruturada em 10 minutos
O vídeo a seguir apresenta uma explicação sobre Programação Estruturada. São 10 minutos
sobre os conceitos do paradigma.
Conteúdo interativo disponível na plataforma de ensino!
Fluxogramas e Programação Estruturada
O vídeo a seguir aborda fluxogramas e Programação Estruturada, mostrando os fundamentos e
as vantagens do paradigma.
Conteúdo interativo disponível na plataforma de ensino!
Programação orientada a objetos:
modelagem de problemas
APRESENTAÇÃO
O paradigma de programação orientada a objetos foi originalmente criado por Alan Kay, autor
da linguagem de programação Smalltalk. Embora seja um paradigma de programação mais novo
no que diz respeito ao seu emprego pelas linguagens de programação, algumas delas já haviam
implementado as suas ideias, sendo a Simula 67, criada em 1967, a primeira linguagem a
realmente utilizar a programação orientada a objetos.
A programação orientada a objetos trouxe uma nova maneira de se pensar projetos de softwares,
sendo que sua aplicação deixa bem clara as etapas de análise, projeto e codificação de softwares.
Seu conceito básico está em abstrair que tudo pode ser classificado como um objeto, cada objeto
implementando atributos e métodos e se relacionando a outros objetos, daí advém seu nome
“programa orientado aos objetos”. Conhecer e entender esse paradigma de programação é
fundamental, já que, atualmente, ele é implementado por muitas linguagens.
Nesta Unidade de Aprendizagem, você vai entender o que é programação orientada a objetos,
bem como vai conhecer algumas linguagens que o implementam e como são aplicados os seus
conceitos.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Definir programação orientada a objetos.•
Identificar as linguagens orientadas a objetos.•
Aplicar a programação orientada a objetos.•
DESAFIO
O principal conceito da programação orientada a objetos é que todo programa é uma coleção de
objetos que se relacionam e apresentam comportamentos e atributos únicos.
Uma empresa contratou você para desenvolver um programa simples em uma linguagem
orientada a objetos. O escopo desse programa é controlar os pedidos feitos em uma lanchonete.
A seguir, no Desafio, veja como os pedidos são feitos atualmente e como eles deverão ser
realizados após o desenvolvimento do programa:
Com base nos requisitos que você viu, elabore uma descrição das possíveis classes, métodos e
atributos que seu programa deve apresentar para contemplar o escopo desse cenário. Agora, os
atributos e os métodos não precisam ser definidos, apenas identificados.
INFOGRÁFICO
A programação orientada a objetos contém alguns conceitosconsiderados pilares desse
paradigma. Para que uma linguagem de programação realmente seja considerada orientada a
objetos é necessário que ela implemente os pilares abstração, encapsulamento, herança e
polimorfismo.
A seguir, no Infográfico, veja o significado de cada um desses conceitos e o porquê de sua
relevância para a programação:
CONTEÚDO DO LIVRO
O paradigma de orientação a objetos é amplamente implementado pelas linguagens de
programação existentes. A programação orientada a objetos permite que o desenvolvimento de
um programa resulte de uma organização do contexto a que se propõe, implementando seu
universo como uma coleção de objetos que se relacionam e de que se abstraem características e
métodos únicos.
Leia o capítulo Programação orientada a objetos: modelagem de problemas, da obra
Paradigmas de programação, e veja como as linguagens de ampla adoção implementam esse
paradigma e, ainda, confira alguns exemplos de implementação de código em linguagem
orientada a objetos.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação orientada
a objetos: modelagem
de problemas
Objetivos de aprendizagem
Ao final deste texto, você deverá apresentar os seguintes aprendizados:
� Definir programação orientada a objetos.
� Identificar as linguagens orientadas a objetos.
� Aplicar a programação orientada a objetos.
Introdução
A programação orientada a objetos (POO) surgiu como um paradigma
que apresentava uma disciplina para novos projetos de desenvolvimento
de software. Etapas com análise e projeto de software que, em outros
paradigmas, acabavam sendo minimizados na POO, se tornam requisitos
fundamentais.
Não é difícil imaginar que a POO acabou se tornando um padrão con-
sumido pela engenharia de software e que possibilitou avanços significati-
vos na programação de computadores. Seu uso permitiu que reutilização
de código se tornasse algo praticamente comum em desenvolvimento
de software, servindo como base para novos conceitos, como os serviços.
Neste capítulo, você entenderá o conceito de POO, conhecerá al-
gumas linguagens que implementam esse paradigma e exemplos de
aplicação em projetos de programas de computador.
Programação orientada a objetos
O conceito de POO tem suas raízes na linguagem de programação Simula 67,
criada por Alan Kay, o precursor dos conceitos desse paradigma de programa-
ção. Contudo, sua grande evolução foi totalmente alcançada com a chegada
da linguagem de programação Smalltalk 80:
De fato, algumas pessoas consideram Smalltalk o modelo base para uma
linguagem de programação puramente orientada a objetos. Uma linguagem
orientada a objetos deve fornecer suporte para três recursos chave de lingua-
gem: tipos de dados abstratos, herança e vinculação dinâmica de chamadas
a métodos (SEBESTA, 2018, p. 547).
Linguagens que suportam a POO são, atualmente, muito usadas. Algumas
das linguagens de programação mais novas, projetadas para a POO, não
implementam mais conceitos de linguagens procedurais como as primei-
ras implementavam. Porém, ainda assim, empregam estruturas básicas da
programação estruturada e são imperativas, como as linguagens Java e C#,
atualmente muito utilizadas e consideradas exemplos de sucesso de POO.
Smalltalk 80 foi primeira linguagem a implementar completamente os
conceitos da POO, pois, em 1980, mesmo com a evolução dos módulos e pacotes
pelas linguagens de programação da época, os problemas ainda persistiam. Um
dos maiores problemas com os recursos atuais era que não existia mecanismo
para inicialização e finalização automática do tipo fornecido. Segundo Tucker
e Noonan (2009, p. 307) “As inicializações normalmente necessárias incluem
abertura de um arquivo, alocação de memória e inicialização de variáveis locais
ao módulo”. Já quanto às finalizações, incluem o fechamento de arquivos e
a liberação de memória.
Além disso, alguns programadores e projetistas começaram a perceber
que algumas necessidades não eram atendidas com as atuais linguagens de
programação imperativa de decomposição funcional e abstração de dados,
como os padrões de graphical user interfaces (GUI), que poderiam ser melhor
implementadas com o conceito de objetos que pudessem trocar mensagens
uns com os outros. Uma GUI poderia ser mais facilmente implementada se
considerarmos, por exemplo, que seus componentes (botões, áreas de texto,
imagens etc.) são tratados como objetos que podem interagir entre si e com
o usuário do sistema.
Programação orientada a objetos: modelagem de problemas2
Assim, a POO surge como um paradigma centrado no desenvolvimento
de objetos, no lugar da atual decomposição funcional e abstração de dados.
Na Figura 1, você pode perceber um pouco dessa diferença entre a atual
programação estruturada e o conceito de objetos.
Figura 1. Comparativo entre programação estruturada e objetos.
Fonte: Adaptada de Gasparotto (2014).
...
...
...
...
...
Dados
globais
Programação estruturada
Procedimento
Procedimento
Procedimento
Procedimento
Procedimento
Dados objeto
Dados objeto
Dados objeto
POO
Método
Método
Método
Método
Método
Método
Em uma linguagem de POO, o encapsulamento dos tipos de dados e suas
funções é alcançado por meio da implementação das classes. Uma classe é
uma declaração de um tipo de objeto que encapsula os seus tipos de dados
pelos seus atributos e funções por meio de seus métodos. É comum ouvir falar
que uma classe serve como uma matriz de objetos, pois, ao determinar os seus
atributos e métodos, serve como um modelo para que diversas instâncias de
um objeto sejam criadas a partir de sua estrutura.
Ao analisar a Figura 1, você pode perceber que um programa em progra-
mação estrutural possui um desempenho melhor que um mesmo programa
em POO, e isso ocorre pelo fato de, na programação estruturada, um código
ser executado após o outro sequencialmente, ao passo que na POO são ne-
cessários alguns desvios. Entretanto, a POO traz outros pontos que acabam
sendo mais interessantes no contexto de aplicações modernas. Como, na
maioria das aplicações, o desempenho das aplicações não é uma das grandes
preocupações (devido ao poder de processamento dos computadores atuais),
a POO se tornou muito difundida.
3Programação orientada a objetos: modelagem de problemas
Na próxima seção, vamos abordar como as linguagens Java, C# e Python
implementam os conceitos da POO. Essas linguagens serão exemplos por serem
muito utilizadas atualmente no contexto de desenvolvimento de software.
Linguagens orientadas a objetos
Agora, você entenderá um pouco sobre as linguagens Java, C# e Python,
atualmente muito utilizadas e que implementam os conceitos da POO.
Java é uma linguagem de programação que foi desenvolvida pela Sun
Microsystems no início da década de 1990. Ela se tornou um símbolo da POO,
inclusive causando certa confusão, por julgarem que a POO era um paradigma
de Java e não ao contrário (MACHADO; FRANCO; BERTAGNOLLI, 2016,
p. 54).
De fato, a característica mais marcante da linguagem de programação
Java está relacionada a sua portabilidade, pois os sistemas construídos não
são compilados em código nativo da plataforma. Programas em Java são
compilados para um bytecode, que é executado por uma máquina virtual, a
Java virtual machine, que permite que os programas escritos em Java possam
ser rodados em qualquer plataforma compatível com a sua máquina virtual.
Em Java, todo o programa usa classes e objetos, e é fundamental que o
programador compreenda esses conceitos da POO para conseguir programar
em Java. Os programas são escritos em pequenos pedaços separados, chamados
de objetos. Segundo Machado, Franco e Bertagnolli (2016, p. 78), “Objetos
são pequenos programas que guardam dentro de si os dados — em suma, as
variáveis — que precisam para executar suas tarefas”. Os objetos também
trazem em si, como sub-rotinas, as instruções para processar esses dados.
As variáveis que um objeto guarda são chamadasde atributos, e as suas sub-
-rotinas são chamadas de métodos.
Programação orientada a objetos: modelagem de problemas4
Veja o exemplo de uma classe Cachorro em Java com os atributos nome,
peso, altura e cor e o método pular().
public class Cachorro{
public String nome;
public float peso;
public float altura;
public String cor;
void pular{
if(altura>=80){
System.out.println("Seu Cachorro pula alto");
}
}
}
Como você pode observar, a programação em Java é praticamente regrada
pelos conceitos de POO, e as classes são a base de qualquer código Java.
Qualquer análise para um novo programa em Java deve partir do entendimento
do seu contexto e projeção das classes.
Agora, vamos analisar a linguagem C#. A linguagem C# (lê-se C Sharp)
é definida pela Microsoft, que a desenvolve como uma linguagem de POO
que faz parte de sua plataforma de desenvolvimento .NET. Embora a lingua-
gem C# tenha sido criada totalmente do zero pela Microsoft, foi baseada na
linguagem C++, e possui muitos elementos das linguagens Java e Pascal.
A plataforma .NET na qual teve seu desenvolvimento inicial, apresentou
algumas limitações que motivaram que, em 1999, fosse montada uma força
tarefa para o desenvolvimento de uma nova linguagem para essa plataforma.
Segundo Ledur (2018, p. 108):
A criação da linguagem C# ajudou muito no desenvolvimento do .NET, pois
a plataforma não precisou se adequar a nenhum código de alguma linguagem
já existente. O C# foi criado especificamente para .NET, sendo que muitas
outras linguagens têm suporte à C#.
5Programação orientada a objetos: modelagem de problemas
Os principais objetivos do projeto da linguagem C# são:
� Ser simples moderna e de propósito geral OO.
� Ter uma linguagem e suas implementações que forneçam suporte para
princípios de engenharia de software.
� Ser destinada à utilização no desenvolvimento de componentes de
software.
� Possibilitar a portabilidade dos programas escritos em C#, assim como
é possível na linguagem Java.
� Fornecer suporte para a escrita de programa, tanto hospedados local-
mente como incorporados.
A Figura 2 mostra um exemplo da estrutura de uma classe em C#.
Figura 2. Exemplo da estrutura de uma classe em C#.
Fonte: Rodrigues (2017, documento on-line).
Você pode perceber que, assim como em Java, C# possui uma estrutura
semelhante com a declaração dos atributos da classe logo no início e depois em
seus métodos, além de uma semelhança na sintaxe entre as duas linguagens,
o que é explicado devido ao embasamento do C# na linguagem Java.
Programação orientada a objetos: modelagem de problemas6
Para finalizar esta seção, vamos abordar a POO na linguagem de progra-
mação Python, que é uma linguagem de programação bastante utilizada por
sua facilidade de aprendizado, aliada as suas características de programação
de alto nível, de script, imperativa, OO e interpretada.
Python é uma linguagem que permite o desenvolvimento tanto no conceito
de programação estruturada como a POO. Possui suporte a tipificação dinâ-
mica, recursos de gerenciamento de uso de memória, além de oferecer uma
abrangente biblioteca padrão. Os interpretadores Python possuem suporte
para diversos sistemas operacionais, possibilitando a adaptação dos sistemas
construídos.
A origem do nome Python, apesar de confundido com o animal cobra,
na realidade é oriunda do grupo de comédia britânico que era assistido pelo
criador da linguagem, chamado Monty Python, formado por Graham Cha-
pman, John Cleese, Eric Idle, Michael Palin, Terry Jones e Terry Gilliam.
Carinhosamente, são chamados de Pythonistas os programadores Python,
e as referências aos trabalhos do grupo de comédia estão espalhadas pelos
tutoriais e sua documentação (LUTZ; ASCHER, 2007).
Python é uma linguagem muito simples, fácil de usar e aprender, apesar
disso, também é uma linguagem extremamente robusta e utilizada nas mais
diversas soluções:
� back-end de sistemas Web, customer relationship management (CRM),
ou gerenciamento de relacionamento com o cliente;
� pesadas simulações de engenharia;
� processamento pesado de efeitos especiais de filmes;
� soluções de análise de dados (data analytics);
� aprendizado de máquina, do inglês machine learning (ML).
Veja o exemplo de uma classe Pessoa em Python.
class Pessoa:
def _ init _ (self, nome, idade):
self.nome = nome
self.idade = idade
def setNome(self, nome):
self.nome = nome
7Programação orientada a objetos: modelagem de problemas
def setIdade(self, idade):
self.idade = idade
def getNome(self):
return self.nome
def getIdade(self):
return self.idade
Apesar da sintaxe do Python ser um pouco diferente da sintaxe de Java e
C#, é possível verificar a estrutura da classe com a definição de atributos e
métodos e que Python é outro exemplar de linguagem OO. Na próxima seção,
você verá alguns exemplos da aplicação da programação OO em classes de
exemplos, para fixar o entendimento.
Desenvolvendo com programação
orientada a objetos
Para ajudar a elucidar o conceito de POO, vamos começar analisando a se-
guinte situação: um exemplo em Java que demonstra a criação da classe
Pessoa com os atributos nome, dataNascimento e CPF; e o método
tirarCopias, que calcula o custo da geração de cópias em um sistema de
gestão de impressões de uma escola. Esse sistema deve calcular o valor da
cópia embasado na seguinte regra:
� para alunos da escola, o valor unitário da cópia será de R$ 0,07;
� para os demais usuários, o valor unitário será de R$ 0,10.
A diferença é que este requisito será implementado com os seguintes
conceitos da POO:
� classes;
� heranças.
Programação orientada a objetos: modelagem de problemas8
Observe na Figura 3, onde consta a classe Pessoa.
Figura 3. Classe Pessoa em Java.
Fonte: Geovane (2012, documento on-line).
Na classe Pessoa podemos observar os seguintes atributos:
� nome;
� cpf;
� data_nascimento.
Observamos, também, que essa classe possui o método tirarCopias,
que faz o cálculo do valor da cópia para pessoas em geral, ou seja, pessoas
que não são alunos. Porém, você pode estar se perguntando, onde estão os
dados do aluno e o método que faz o cálculo do valor da cópia quando se
trata de um aluno?
Esses dados estão na classe Aluno, mas, como o Aluno também é uma
pessoa e tem alguns atributos que são comuns as demais pessoas, não vamos
repetir na classe Aluno. A Figura 4 mostra como ficaria a classe Alunos
em Java.
9Programação orientada a objetos: modelagem de problemas
Figura 4. Classe Alunos em Java.
Fonte: Geovane (2012, documento on-line).
É possível, portanto, observar que no início da classe Aluno existe a
declaração extends. Essa declaração significa que a classe Aluno está
dizendo que herda a classe Pessoa, dessa forma, os atributos que são comuns
à classe Pessoa não necessitam ser repetidos. Além disso, percebe-se que a
classe Aluno possui o atributo matrícula, que é específico do Aluno.
Por fim, veja que, na classe Aluno, o método tirarCopias é alterado
de acordo com o valor específico para os Alunos, o que é possível em razão
de um outro recurso de POO: o polimorfismo. Polimorfismo é um recurso que
permite ao objeto ter um comportamento diferente, dependendo da situação.
Nesse caso, o cálculo do valor da cópia se altera por conta da situação de
desconto de aluno.
Pelos exemplos apresentados, percebe-se na prática alguns recursos e usos
da programação OO e seus benefícios para a programação, possibilitando,
principalmente, a reutilização do código.
Conceitos como os observados nos exemplos das Figuras 3 e 4 são casos
comuns em POO, por isso é importante todo programador conseguir abstrair
classes com seus atributos e métodos separados e, quando utilizar conceitos
bases da POO, como herança de classes, evitar reutilização de código.
Programação orientada a objetos: modelagem de problemas10
GASPAROTTO,H. M. Os 4 pilares da Programação Orientada a Objetos. DevMedia,
Rio de Janeiro, 2014. Disponível em: https://www.devmedia.com.br/os-4-pilares-da-
-programacao-orientada-a-objetos/9264. Acesso em: 15 set. 2019.
GEOVANE, H. Entendendo e Aplicando Herança em Java. DevMedia, Rio de Janeiro, 2012.
Disponível em: https://www.devmedia.com.br/entendendo-e-aplicando-heranca-em-
-java/24544. Acesso em: 15 set. 2019.
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
LUTZ, M.; ASCHER, D. Aprendendo Python. 2. ed. Porto Alegre: Bookman; O’Reilly, 2007.
566 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
RODRIGUES, J. Como criar minha primeira classe em C#. DevMedia, Rio de Janeiro, 2017.
Disponível em: https://www.devmedia.com.br/como-criar-minha-primeira-classe-em-
-csharp/38785. Acesso em: 15 set. 2019.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2.
ed. Porto Alegre: AMGH, 2009. 630 p.
Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
MILETTO, E. M.; BERTAGNOLLI, S. C. Desenvolvimento de software II: introdução ao de-
senvolvimento web com HTML, CSS, JavaScript e PHP. Porto Alegre: Bookman, 2014.
276 p. (Série Tekne; Eixo Informação e Comunicação).
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
11Programação orientada a objetos: modelagem de problemas
DICA DO PROFESSOR
Todo paradigma de programação tem vantagens e desvantagens, mas saber equilibrar os pontos
positivos e negativos, entendendo qual é o melhor para determinada situação, é o desafio de um
profissional de desenvolvimento de software.
A seguir, na Dica do Professor, veja algumas vantagens e desvantagens do paradigma de
programação orientado a objetos, o que possibilitará o entendimento de quando é necessária a
adoção de uma linguagem orientada a objetos.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) O conceito principal da programação orientada a objetos, que justifica o nome do
próprio paradigma, é que tudo pode ser abstraído para um objeto e, assim, um
programa seria uma coleção de objetos que se relacionam e apresentam
comportamento único. Assinale a alternativa que apresenta os principais
componentes de um objeto:
A) Estados e atributos.
B) Métodos e colunas.
C) Tabelas e variáveis.
D) Atributos e métodos.
E) Estado e métodos.
A orientação a objetos trouxe alguns conceitos interessantes para a programação, e 2)
um deles está relacionado ao conhecimento sobre a implementação interna da classe,
o qual é desnecessário do ponto de vista do objeto. Assinale a alternativa correta
quanto ao seu nome:
A) Relacionamentos.
B) Encapsulamento.
C) Classes.
D) Abstração.
E) Herança.
3) Um dos novos conceitos surgidos sobre a programação orientada a objeto é o de que
ela é um mecanismo por meio do qual é possível selecionar as funcionalidades
utilizadas de forma dinâmica por um programa no decorrer de sua execução.
Assinale a alternativa correta que apresenta o nome desse mecanismo:
A) Atributos.
B) Herança.
C) Classes.
D) Abstração.
E) Polimorfismo.
Uma das grandes vantagens da adoção da programação orientada a objetos é a 4)
reutilização de código e sua organização. Com relação às vantagens da reutilização de
código na programação orientada a objetos, assinale a alternativa correta:
A) A reutilização de código é obtida pelo uso de funções nos programas.
B) Os códigos em linguagens OO são simplificados pelo uso de procedimentos.
C) A reutilização de código é consequência da análise e do projeto de código.
D) A reutilização de código é consequência de métodos e eventos.
E) A reutilização de código se obtém após a sua simplificação.
5) Um objeto é uma instância de uma classe em programação orientada a objetos. As
classes definem, então, a estrutura dos objetos que serão instanciados a partir dela.
Com base nessa afirmativa, analise a classe a seguir em Java e assinale a alternativa
correta:
public class Bola
{
String cor;
int tamanho;
boolean cheia;
void encher()
{
cheia = true;
}
void esvaziar()
{
cheia = false;
}
}
A) Cor, tamanho e cheia são métodos da classe bola.
B) Esvaziar e encher são atributos do tipo void, da classe bola.
C) Cor, tamanho e cheia são atributos da classe bola.
D) Esvaziar, encher e cheia são métodos da classe bola.
E) Cor e tamanho são atributos e cheia método booleano da classe bola.
NA PRÁTICA
Python é uma linguagem de programação orientada a objetos com grande aceitação no
mercado. Atualmente, ela está entre uma das linguagens de programação mais utilizadas,
principalmente por ser uma linguagem de fácil aprendizado que possibilita a profissionais
conhecedores de qualquer outra linguagem orientada a objetos implementar programas
rapidamente. Além disso, ela pode se adaptar a diferentes contextos de negócio.
A seguir, no Na Prática, veja o desenvolvimento de uma estrutura simples com operações
básicas para serem utilizadas no gerenciamento de uma conta de um banco e confira como a
linguagem Python implementa a programação orientada a objetos:
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Entendendo a orientação a objetos
A programação orientada a objetos é um paradigma de programação, isto é, uma forma de
programar e desenvolver um sistema baseada no conceito de objetos, que podem conter dados
na forma de campos, os quais também são denominados atributos, e códigos, na forma de
procedimentos conhecidos como métodos. No vídeo a seguir, veja o conceito de orientação a
objetos, classes, atributos e métodos.
Conteúdo interativo disponível na plataforma de ensino!
Aplicando herança em Java
Quando se faz uma programação em Java, existe a necessidade de se trabalhar com várias
classes. Isso se explica pelo fato de que, na maioria das vezes, classes diferentes apresentam
características comuns e, assim, ao invés de criar outra classe com essas características, é
possível usar as características de um objeto ou classe já existente. Essa é a herança. Confira, no
vídeo a seguir, a aplicação do conceito de herança em JAVA.
Conteúdo interativo disponível na plataforma de ensino!
Programação orientada a objetos:
classes, relacionamentos e
encapsulamento
APRESENTAÇÃO
As classes são parte fundamental da programação orientada a objetos; são estruturas utilizadas
em linguagens de programação,
que implementam o paradigma desse tipo de orientação.
Elas, ainda, definem a modelagem estática dos objetos. Para que os objetos possam implementar
conceitos, definidos pelo paradigma
de orientação, o suporte das classes é necessário.
Os relacionamentos entre objetos são fundamentais, pois estes implementam entidades da
realidade. Porém, necessita-se de segurança para que um objeto não "entenda" ou "saiba" como
outro implementa determinada rotina e, nesse conceito,
o encapsulamento faz importante papel.
Nesta Unidade de Aprendizagem, você aprenderá mais sobre classes e relacionamentos e
entenderá sobre encapsulamento, na perspectiva
da orientação a objetos.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentaros seguintes aprendizados:
Analisar as classes na perspectiva de orientação a objetos.•
Descrever os relacionamentos na perspectiva de orientação
a objetos.
•
Explicar o que é o encapsulamento.•
DESAFIO
As classes possuem diferentes tipos de relacionamentos, que possibilitam especificar
comportamentos e necessidades diferentes. Exemplo: relacionamentos de associação (agregação
ou composição) são tipos distintos e são utilizados para representar situações
diferenciadas; assim como os relacionamentos de herança (generalização ou especialização) são
utilizados para representar situações de heranças entre classes.
Imagine que você está participando da etapa de análise e projeto de um sistema que será
construído em uma linguagem orientada a objetos e o escopo do sistema, definido até o
momento, considera o seguinte:
Sem se preocupar com atributos e métodos, você deverá identificar as possíveis classes e seus
relacionamentos, justificando a sua escolha.
INFOGRÁFICO
Entender o conceito e o porquê de existirem diferenças entre os relacionamentos de classes, está
diretamente relacionado a conceitos e fundamentos base da programação orientada a objetos.
Saber quando utilizar cada um, na representação de modelos, faz toda a diferença na correta
implementação desse tipo de programa.
Neste Infográfico, veja uma síntese dos tipos de relacionamentos e quando eles devem ser
aplicados em modelos de programas orientado a objetos.
CONTEÚDO DO LIVRO
Trabalhar com linguagens de programação orientada a objetos é, necessariamente, trabalhar com
classes; é praticamente impossível separar um do outro. Por isso, conhecer a estrutura das
classes e seus conceitos e entender os diferentes tipos de relacionamentos que se pode ter para
que os conceitos de orientação a objeto, como herança e encapsulamento, sejam implementados,
é base para qualquer profissional de sucesso.
No capítulo Programação orientada a objetos: classes, relacionamentos e encapsulamento, da
obra Paradigmas de programação, serão abordadas a definição e as partes de uma classe, sobre
a importância e o significado dos tipos de relacionamento que podem existir, bem como o
conceito de encapsulamento.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação orientada
a objetos: classes,
relacionamentos e
encapsulamentos
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Analisar as classes na perspectiva de orientação a objetos.
� Descrever os relacionamentos na perspectiva de orientação a objetos.
� Explicar o que é encapsulamento.
Introdução
Na programação orientada a objetos, as classes desempenham um papel
fundamental. Classes são estruturas que determinam a descrição de um
conjunto de objetos que a utilizam como base e, dessa forma, são nas
classes que são definidos os atributos e métodos que os objetos podem
conter. Por essa razão, as classes são denominadas matriz de um objeto
e determinam seu escopo.
Existem conceitos básicos em programação orientada a objetos, entre
eles, o conceito que determina que apenas os métodos do próprio objeto
devem manipular seus atributos, garantindo acesso direto à propriedade
do objeto, adicionando outra camada de segurança à aplicação. As classes
devem possibilitar diferentes tipos de relacionamentos e, assim sendo,
diferentes tipos de relacionamento são previstos.
Neste capítulo, você irá compreender o que são as classes na pers-
pectiva da orientação a objetos, além de aprender sobre seus relaciona-
mentos e o conceito de encapsulamento.
Classes na orientação a objetos
As classes são as estruturas de código mais importantes de qualquer sistema
orientado a objetos. Segundo Booch, Rumbaugh e Jacobson (2006, p. 45),
“uma classe é uma descrição de um conjunto de objetos que compartilham
os mesmos atributos, operações, relacionamentos e semântica”. As classes
são utilizadas para expressar todo o vocabulário e escopo do sistema a ser
desenvolvido.
É praticamente impossível falar em orientação a objetos sem relacioná-la
ao conceito de classes. Dessa forma, não é difícil imaginar a importância da
construção de classes bem estruturadas, que consigam delimitar corretamente
as fronteiras e os relacionamentos para, assim, realizar a distribuição correta
das responsabilidades dentro de um sistema orientado a objetos.
O paradigma de programação orientada a objetos envolve a identificação e
abstração de entidades, de acordo com o escopo de um sistema. Essas entidades
formam o vocabulário do sistema. Por exemplo, se estamos desenvolvendo
um sistema para um consultório médico, entidades como prontuário, paciente,
médico, etc., fazem parte do vocabulário e serão implementadas pelas classes.
As classes são representadas graficamente por um retângulo. A Figura 1 ilustra
a representação de uma classe conforme a Unified Modeling Language (UML).
Figura 1. Representação da estrutura de uma classe.
Fonte: Ricarte (2003, documento on-line).
Segundo Lima (2014, p. 49), “uma classe é uma descrição de um conjunto
de objetos que compartilham os mesmos atributos, operações, relacionamentos
e semântica”.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos2
Cada classe deve possuir um nome que a diferencie das demais. O nome é
dito simples quando contém uma só sequência de caracteres, ou qualificado,
quando além do nome da classe, possui um prefixo que identifica o nome do
pacote a qual a classe pertence. Algumas representações de classes podem ser
apenas o seu nome. Por padrão, o nome da classe sempre começa com letra
maiúscula, como no exemplo a seguir.
� Cliente.
� Parede.
� Sensor de temperatura.
Outra propriedade de uma classe são os atributos. Um atributo é uma
propriedade de uma classe e também são chamados de variáveis ou campo. É
pelos atributos que podemos definir o estado de um objeto, fazendo com que
esses valores possam ser alterados. Um atributo é, portanto, uma abstração do
tipo de dado ou de estados que os objetos da classe podem abranger.
Um atributo pode ser indicado por sua classe e, possivelmente, um valor
inicial padrão. O exemplo a seguir mostra um código em Java com a definição
dos atributos de uma classe Cachorro:
public class Cachorro{
public String nome;
public int peso;
public String corOlhos;
public int quantPatas;
}
Outra propriedade de uma classe são as operações ou métodos. Uma ope-
ração ou método é a implementação de um serviço que pode ser acionado
por algum objeto da classe, ou seja, são as operações que podem determinar
o comportamento dos objetos. Um método pode também ser definido como
uma abstração de algo que pode ser feito com determinado objeto e que pode
ser compartilhado por todos os objetos da classe.
Segundo Booch, Rumbaugh e Jacobson (2006, p. 53), “uma classe pode
ter qualquer quantidade de métodos ou até mesmo nenhum método definido”.
Os métodos ou operações podem ser especificados pela indicação de sua
assinatura, que contém nome, tipo e valor padrão de todos os parâmetros. O
exemplo de código a seguir mostra a definição em Java do método latir
para a mesma classe Cachorro:
3Programação orientada a objetos: classes, relacionamentos e encapsulamentos
class Cachorro {
int tamanho;
String nome;
void latir() {
if(tamanho > 60)
System.out.println("Wooof, Wooof!");
else if(tamanho > 14)
System.out.println("Ruff!, Ruff!");
else
System.out.println("Yip!, Yip!");
}
}
Além disso, as classes definem reponsabilidades. Uma reponsabilidade é
o conceito de que uma classe deve executar uma única responsabilidade no
sistema e essa responsabilidade deve ser executada por esta única classe, sem
ser repetida por outra classe do sistema.
Se temos, em um sistema, duas classes compartilhando uma determinada
responsabilidade, estamos ferindo esse conceito. Se ao se referira uma deter-
minada classe, você diz: “minha classe tem as informações do cliente e pode
salvá-las no banco de dados”, perceba que o “e” na frase, indica mais de uma
responsabilidade. A seguir, vamos abordar os tipos de relacionamentos que
as classes podem estabelecer.
Relacionamentos
Ao trabalhar com a orientação a objetos, percebemos que, assim como no
mundo real, existe um número muito pequeno de classes que podem trabalhar
sozinhas em qualquer sistema. Ao contrário, temos a maioria das classes
colaborando com as outras, de diferentes maneiras. Dessa forma, ao traba-
lharmos com a definição e a modelagem de um sistema a ser construído em
uma linguagem orientada a objetos, não é possível ater-se somente a identificar
as classes que fazem parte do escopo desse sistema, mas também é preciso
entender e modelar, os relacionamentos, ou seja, o modo como essas classes
se relacionam entre si.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos4
Segundo Tucker e Noonan (2009, p. 275), “existem três tipos de relaciona-
mento especialmente importantes”, conforme vemos a seguir.
� Dependências: representam os relacionamentos de utilização entre
classes.
� Generalizações: representam o relacionamento entre classes mães e
suas classes herdeiras.
� Associações: representam os relacionamentos estruturais entre objetos:
■ agregações: tipo de associação na qual o objeto dependente pode
existir mesmo sem o objeto pai;
■ composição: tipo de associação na qual a existência do objeto de-
pendente só faz sentido se o objeto pai existe.
Cada um desses relacionamentos fornece uma forma diferente de combina-
ções e de abstrações. A dependência é um relacionamento de utilização entre
classes e se caracteriza por um tipo de relacionamento no qual a mudança em
uma classe pode afetar o comportamento ou estado de outra classe.
As dependências podem ser usadas no contexto de classes para mostrar
que uma classe usa outra como argumento na assinatura de uma operação. Ou
seja, a dependência indica que um objeto depende da especificação de outro.
Uma dependência é representada graficamente por uma linha tracejada,
ligando duas classes, com uma seta apontando para a classe da qual a outra
depende. A Figura 2 ilustra um exemplo de dependência entre as classes
Sistema e Pessoa.
Figura 2. Relacionamento de dependência entre classes.
Fonte: Nogueira (2006, documento on-line).
5Programação orientada a objetos: classes, relacionamentos e encapsulamentos
Um relacionamento de dependência pode ter um nome, apesar de os nomes
raramente serem necessários, a menos que tenha um modelo com muitas
dependências e seja necessário fazer uma referência a elas (BOOCH; RUM-
BAUGH; JACOBSON, 2006).
A generalização é um relacionamento entre superclasses ou classes mães
e seus tipos mais específicos são também chamados de subclasses ou classes
filhas. A generalização significa que os objetos da classe filha podem ser
utilizados em qualquer local que a classe mãe ocorra, mas não vice-versa.
Em outras palavras, a generalização significa que a classe filha pode ser
substituível por uma declaração da classe mãe.
Como em um relacionamento do tipo generalização as classes filhas herdam
os atributos e métodos da classe mãe, é necessário que na classe filha sejam
então especificados somente os atributos e métodos que lhe são específicos,
sendo os demais herdados da classe mãe e, por isso, desnecessários para sua
declaração.
Os relacionamentos de generalização podem ser de uma classe mãe para
várias classes filhas, ou uma classe filha pode herdar de diferentes classes
mães (TUCKER; NOONAN, 2009).
Para entender melhor esse conceito, imagine uma classe mãe ou superclasse
chamada Veículo, na qual são definidos os atributos comuns a qualquer
veículo (cor, chassi, placa), e sua relação com as classes filhas Carro e
Moto. Como esses atributos se repetem tanto para um objeto do tipo Carro
quanto para um objeto do tipo Moto, não é necessário repetir os atributos
nessas classes. A seta vazada apontando para a superclasse identifica que
existe um relacionamento de generalização entre as classes. A Figura 3 ilustra
esse exemplo.
A associação é um tipo de relacionamento estrutural que especifica quais
objetos de uma classe estão conectados a objetos de outra. A partir de uma
associação entre objetos é possível navegar de um objeto ao outro. A associação
é o tipo mais comum de relacionamento e sinaliza que os objetos de uma classe
estão conectados a objetos de outra.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos6
Figura 3. Relacionamento de generalização entre classes.
Fonte: Vasconcelos (2011, documento on-line).
Sem essa associação, nenhuma mensagem pode passar entre os objetos da
classe em tempo de execução. Existe uma associação entre duas classes se uma
instância de uma destas reconhecer a existência da outra, de modo a realizar
seu trabalho. Em um diagrama, uma associação é representada por uma linha
conectando duas classes. Podemos representar o direcionamento da associação
colocando setas abertas nas extremidades da linha. Com isso, pode-se definir
como é feita a navegação entre classes. Quando não se colocam setas, a navegação
é definida como bidirecional (BOOCH; RUMBAUGH; JACOBSON, 2006).
A Figura 4 mostra um tipo de relacionamento de associação simples entre
a classe Cliente e Consulta.
Figura 4. Associação simples entre classes.
Fonte: Leon (2009, documento on-line).
7Programação orientada a objetos: classes, relacionamentos e encapsulamentos
O relacionamento de agregação é usado sempre que queremos indicar
que o objeto de uma classe pode colaborar com a existência de um objeto de
outra, mas a existência desse objeto não é obrigatória. Também é conhecida
como associação em que um objeto é parte de outro, de tal forma que pode
existir sem o outro ou pode, ainda, ser chamada de associação fraca, devido
ao conceito de que um pode existir sem o outro. Também podemos dizer que
é uma relação do tipo “todo/parte” ou “possui um”, sendo o último mais utili-
zado em casos em que uma classe representa algo grande composto por coisas
menores (classes agregadas). A Figura 5 ilustra um tipo de relacionamento de
agregação entre classes.
Figura 5. Agregação entre classes.
Fonte: Leon (2009, documento on-line).
Por fim, o relacionamento de composição simboliza um tipo de asso-
ciação mais forte entre as classes, pois neste tipo de relacionamento não faz
sentido um objeto parte continuar existindo sem a existência de um objeto
parte. Quando se tem uma classe que depende de outra para ser utilizada, e
quando se destrói essa classe a outra também deve ser apagada, temos um
Programação orientada a objetos: classes, relacionamentos e encapsulamentos8
relacionamento de composição. A Figura 6 ilustra um tipo de relacionamento
de composição entre classes.
Figura 6. Composição entre classes.
Fonte: Leon (2009, documento on-line).
Encapsulamento
O encapsulamento é um dos conceitos básicos da programação orientada a
objetos. Esse conceito está ligado à técnica de fazer com que detalhes internos
do funcionamento dos métodos de uma classe não sejam de conhecimento
dos objetos que a utilizam. Dessa forma, os objetos não têm que se preocupar
com o modo como o método executa um determinado bloco de código, pois
são apenas acionados pelo objeto e são retornados.
O encapsulamento também é aplicado aos atributos de uma classe. Isso
faz com que um objeto esconda seus dados de outros e permite que os dados
sejam manipulados e acessados somente pelos próprios métodos do objeto
(TUCKER; NOONAN, 2009). O conceito de encapsulamento possibilita os
seguintes ganhos:
9Programação orientada a objetos: classes, relacionamentos e encapsulamentos
� proteger os dados de um objeto de uso arbitrário e não intencional;
� ocultar de um usuário os detalhes da implementação;
� separar a maneira como um objeto se comporta da maneira comoestá
implementado;
� definir como implementar os conhecimentos ou ações de uma classe,
sem informar como isto é feito.
Um exemplo para ilustrar o conceito de encapsulamento seria um usuário
trocando um canal de televisão pelo controle remoto. Este usuário aperta o
botão e não se importa como o controle remoto se comunica com a televisão
e solicita a troca do canal: ele simplesmente sabe que, ao pressionar o botão,
o canal será selecionado.
Quando você cria um método, sabe que ele está correto e o chama em outra classe,
você está confiando no que fez. Se quiser lembrar a ordem das linhas de código, isto
seria o equivalente a encapsular a troca de mensagens entre os objetos.
Em um processo de encapsulamento, os atributos das classes são do tipo
private. Para acessar esses tipos de modificadores, é necessário criar
métodos setters e getters. Por entendimento, os métodos setters servem para
alterar a informação de uma propriedade de um objeto. Já os métodos getters
servem para retornar o valor dessa propriedade.
O encapsulamento é dividido em dois níveis, conforme vemos a seguir.
� Nível de classe: quando determinamos o acesso de uma classe inteira,
que pode ser public ou Package-Private (padrão);
� Nível de membro: quando determinamos o acesso de atributos ou mé-
todos de uma classe, que podem ser public, private, protected
ou Package-Private (padrão).
Veja, no exemplo a seguir, um código Java implementando os métodos
get e set para os atributos de uma classe.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos10
public class Pessoa {
private String nome;
private String sobrenome;
private String dataNasc;
private String rg;
private String[] telefones;
public String getNome(){
return nome;
}
public void setNome(String n) {
nome = n;
}
public String getSobrenome() {
return sobrenome;
}
public void setSobrenome(String s) {
sobrenome = s;
}
public String getDataNasc() {
return dataNasc;
}
public void setDataNasc(String d) {
dataNasc = d;
}
public String getRg() {
return rg;
}
public void setRg(String r) {
r = rg;
}
public String getTelefones() {
return telefones;
}
public void setTelefones(String[] telefones) {
telefones[] = telefones;
}
}
11Programação orientada a objetos: classes, relacionamentos e encapsulamentos
Quando trabalhamos com programação orientada a objetos, devemos
começar a implementação de uma classe utilizando o nível de acesso pri-
vate, a menos que seja necessário utilizar o public. Fazemos isso porque
é desejável ter como padrão a privacidade dos dados ocultados, protegendo
seu acesso por outro objeto externo. Além disso, membros públicos tendem
a nos ligar a uma implementação em particular e limitar nossa flexibilidade
em mudar o código.
Uma grande vantagem do encapsulamento é que toda parte encapsulada
pode ser modificada sem que os usuários da classe em questão sejam afetados.
No caso de um liquidificador, por exemplo, um técnico poderia substituir o
motor do equipamento por outro totalmente diferente, sem que seu usuário
seja afetado — afinal, ele continuará somente tendo que pressionar o botão.
BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: guia do usuário. 2. ed. Rio de Janeiro:
Elsevier; Campus, 2006. 474 p.
LEON, P. L. Associações entre Classes de Objetos – UML. Pleon’s Blog, [S. l.], 22 fev. 2009.
Disponível em: https://plleon.wordpress.com/2009/02/22/associacoes-entre-classes-
-de-objetos-uml/. Acesso em: 27 set. 2019.
LIMA, A. S. UML 2.5: do requisito à solução. São Paulo: Érica, 2014. 368 p.
NOGUEIRA, A. UML - Unified Modeling Language - Generalização, agregação, com-
posição e dependência. Linha de Código, Rio de Janeiro, 13 fev. 2006. Disponível em:
http://www.linhadecodigo.com.br/artigo/943/uml-unified-modeling-language-ge-
neralizacao-agregacao-composicao-e-dependencia.aspx. Acesso em: 27 set. 2019.
RICARTE, I. L. M. O que é uma classe. Programação Orientada a Objetos – Uma aborda-
gem com Java, Campinas, 27 jun. 2000. Disponível em: http://www.dca.fee.unicamp.
br/cursos/PooJava/classes/conceito.html. Acesso em: 27 set. 2019.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2.
ed. Porto Alegre: AMGH, 2009. 630 p.
VASCONCELOS, N. UML: Diagrama de Classes: Generalização. Tudo que eu gosto e outros
assuntos, [S. l.], 15 jun. 2011. Disponível em: http://tudoqueeugostoeoutrosassuntos.
blogspot.com/2011/06/uml-diagrama-de-classes-generalizacao.html. Acesso em:
27 set. 2019.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos12
Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
13Programação orientada a objetos: classes, relacionamentos e encapsulamentos
DICA DO PROFESSOR
A representação correta de relacionamentos do tipo agregação e composição é importante para
que não existam problemas de interpretação e, consequentemente, de implementação de códigos
em programas construídos em orientação a objetos.
Apesar de ser compreensível, ainda existem muitos desenvolvedores que sentem uma certa
dificuldade no seu entendimento e que, muitas vezes, costumam utilizar a representação errada
ou, até mesmo, não saber ao certo qual a diferença entre os dois tipos.
Na Dica do Professor, você verá, com alguns exemplos, a diferença entre os dois tipos de
associação entre classes, para que não restem dúvidas quanto à correta aplicação.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) Há um tipo específico de relacionamento entre classes, em que o objetivo é mostrar
que as informações de um objeto (chamado objeto todo) necessitam serem
complementadas por um ou mais objetos de outra classe (objeto parte).
Assinale a alternativa abaixo que contenha o nome desse tipo de relacionamento.
A) Composição.
B) Generalização.
C) Associação forte.
D) Especialização.
E) Agregação.
2) Todo o atributo de uma classe só poderá ser manipulado pelos métodos da própria
classe. O objeto, assim, esconde seus dados de outros objetos e permite que os dados
sejam acessados por intermédio de seus próprios métodos.
Quanto a esse conceito, assinale a alternativa correta.
A) Esse conceito é conhecido como encapsulamento.
B) Esse conceito é conhecido como polimorfismo.
C) Esse conceito é conhecido como herança.
D) Esse conceito é conhecido como relacionamentos.
E) Esse conceito é conhecido como abstração.
3) Um tipo de objeto especifica uma família, sem se preocupar em definir como o tipo e
o objeto serão implementados. Na programação orientada a objetos, os tipos são
determinados na etapa de análise.
Assinale a alternativa correta quanto à estrutura utilizada para definir como serão
implementados os tipos de objetos.
A) Atributos.
B) Classes.
C) Associação.
D) Relacionamentos.
E) Herança.
4) Os relacionamentos do tipo herança entre classes apresentam diferenças. Um dos
tiposde relacionamento de herança é indicado quando existe algum atributo que seja
aplicável a mais de uma classe, que contenha os atributos comuns a outras classes
especializadas.
Assinale a alternativa correta quanto ao nome desse tipo de relacionamento.
A) Especialização.
B) Associação.
C) Generalização.
D) Encapsulamento.
E) Herança.
5) Existe um tipo de relacionamento que impõe o sentido de que um objeto todo não
existe sem suas partes. Não se pode ter uma cesta de produtos, sem os seus produtos,
correto?
Assinale a alternativa correta quanto ao nome desse tipo de relacionamento.
A) Generalização.
B) Abstração.
C) Agregação fraca.
D) Composição.
E) Especialização.
NA PRÁTICA
O conceito de encapsulamento é um dos conceitos base da orientação a objetos. Encapsular é
uma forma de garantir restrição de segurança aos valores dos atributos de uma classe. Java é
uma das linguagens de programação orientada a objetos mais utilizadas atualmente e que, como
qualquer outra linguagem que implemente esse paradigma, possui a possibilidade de
implementar encapsulamento.
Neste Na Prática, você verá como o conceito de Encapsulamento é implementado em um
exemplo simples, de uma classe de conta bancária, em linguagem de programação Java; e como
ele é benéfico para garantir restrição de integridade aos atributos.
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Curso POO Java #02b - Criando classes e objetos em Java
Saiba como criar uma classe, com seus atributos e métodos, e a instanciar novos objetos a partir
dessa classe inicial.
Conteúdo interativo disponível na plataforma de ensino!
Curso POO Teoria #07a - Relacionamento entre Classes
Veja como fazer relacionamentos, entre as classes em Java, na orientação a objetos.
Conteúdo interativo disponível na plataforma de ensino!
Linha de código
Neste site, são sintetizados alguns conceitos sobre a programação orientada a objetos.
Conteúdo interativo disponível na plataforma de ensino!
Programação orientada a objetos:
herança e polimorfismo
APRESENTAÇÃO
A reusabilidade de código é uma das grandes vantagens do desenvolvimento de softwares em
linguagens de programação orientada a objetos. Pela estrutura de classes e construção de
programas, pensando em abstrair entidades da realidade para o conceito de objetos, é possível
que os códigos se tornem mais organizados e reutilizáveis.
Quando se pensa em reusabilidade de código em orientação a objetos, é necessário
conhecer como funciona o conceito de herança e polimorfismo.
Nesta Unidade de Aprendizagem, você conhecerá o conceito e tipos de herança e polimorfismo
na visão da orientação a objetos e também como são aplicados, utilizando exemplos em
linguagem de programação orientada a objetos.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Especificar a herança na orientação a objetos.•
Discutir o polimorfismo na orientação a objetos.•
Aplicar a herança e o polimorfismo.•
DESAFIO
A herança é um conceito da programação orientado a objetos que permitem o reuso de código.
Por meio do conceito de herança, novas classes são criadas a partir de classes já existentes,
absorvendo os seus atributos e métodos e adicionando os seus próprios.
A partir disso, considere a seguinte situação:
Conteúdo interativo disponível na plataforma de ensino!
Com base em tais informações e utilizando o conceito de herança, apresente o modelo de classes
e o modelo descritivo com os atributos e métodos das classes necessárias para atender a esse
requisito. Utilize os métodos 'get' e 'set' para manipulação dos atributos de cada classe.
INFOGRÁFICO
O conceito de herança é um dos conceitos base da programação orientada a objetos. Qualquer
linguagem de programação que implemente o paradigma de orientação a objetos deve permitir
que a herança seja implementada.
Neste Infográfico, você verá a sintetização de conceitos relacionados à herança entre classes,
abordando a hierarquia de classes, herança simples e herança múltipla.
CONTEÚDO DO LIVRO
A programação orientada a objetos, sem dúvida, possibilitou que os programas de computadores
ficassem mais próximos da realidade. Avanços relacionados à criação de programas em
linguagens orientadas a objetos vão desde a facilidade de acoplação até mesmo a manutenção de
sistemas.
Outro benefício importante da programação orientada a objetos está ligado ao reuso de código.
E, quando se fala em reuso de código em programação orientada a objetos, é necessário falar
sobre herança e polimorfismo.
No capítulo Programação orientada a objetos: herança e polimorfismo, da obra Paradigmas de
programação, base teórica desta Unidade de Aprendizagem, você vai conhecer mais sobre esses
conceitos da programação orientada a objetos, entender os tipos de herança e as formas de
implementação de polimorfismo em linguagens orientadas a objetos.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação orientada
a objetos: herança
e polimorfismo
Objetivos de aprendizagem
Ao final deste texto, você deverá apresentar os seguintes aprendizados:
� Especificar a herança na orientação a objetos.
� Discutir o polimorfismo na orientação a objetos.
� Aplicar a herança e o polimorfismo.
Introdução
O paradigma da programação orientada a objetos surgiu com o intuito
de aplicar conceitos da realidade ao contexto da programação de com-
putadores. O próprio nome, orientação a objetos, remete ao conceito
de que o foco da construção dos programas está em orientar a estrutura
para as entidades objetos, que emulam noções existentes no mundo real.
Para que o paradigma de orientação a objetos tenha maior abrangên-
cia, faz-se necessário que outros conceitos também sejam possíveis e,
nesse escopo, ocorre a herança entre objetos. Assim como na realidade,
no contexto da programação orientada a objetos, a herança está asso-
ciada à característica de possuir comportamentos de outra entidade.
Neste capítulo, iremos entender o funcionamento do conceito de
herança na programação orientada a objetos. Além disso, abordaremos
o conceito de polimorfismo, que permite que a herança entre objetos
seja possível, mesmo com alterações no comportamento herdado, para
atender a características específicas do objeto herdeiro.
O conceito de herança na orientação a objetos
O conceito de herança na programação orientada a objetos é utilizado para
se permitir a reutilização de um código. A herança possibilita que classes
compartilhem seus atributos e métodos entre si. Segundo Tucker e Noonan
(2009, p. 335),
[...] o paradigma orientado a objetos suporta reutilização de código por in-
termédio da herança. As classes existem em uma linguagem orientada a
objetos em uma hierarquia de classes. Uma classe pode ser declarada como
uma subclasse de outra classe, que é chamada de classe mãe ou superclasse.
Dentro dessa relação de hierarquia de classes é possível que a subclasse
herde atributos e comportamentos da superclasse, simplesmente pelo fato de
ser sua subordinada.
Na programação orientada a objetos, a relação de herança entre classes é
a relação em que uma classe é do tipo é uma, e não do tipo tem uma. Esta é
uma das confusões recorrentes na construção de programas em orientação
a objetos.
Para ilustrar essa diferença, observe a Figura 1 e veja que, neste exemplo,
temos um tipo de relação é uma, pois o objeto da classe Cachorro, assim
como o objeto da classe Gato, é, por herança, um tipo de objeto da classe
Animal.
Figura 1. Representação de herança
entre classes.
Animal
Cachorro Gato
Programação orientada a objetos: herança e polimorfismo2
Compare, agora, a relação apresentada na Figura 2, que representa uma
relação do tipo tem uma. Perceba que, neste caso, uma relação de herança
entre as classes Estado e Cidade não faz sentido, visto que um estado
possui cidades, masuma cidade não é um estado.
Figura 2. Representação da relação do tipo tem uma entre
classes.
Estado Cidade
No conceito de herança, a superclasse geralmente é uma classe genérica,
que engloba os atributos e métodos que podem ser utilizados por qualquer
classe herdeira. Não faz sentido utilizar a superclasse para atribuir, por exem-
plo, um atributo ou método que seja específico de uma subclasse, pois, neste
caso, todas as demais subclasses estariam herdando este atributo ou método
desnecessariamente.
A herança pode apresentar duas formas diferentes. A mais comum e uti-
lizada pelas linguagens de programação, em geral, é a herança simples. No
entanto, algumas linguagens de programação orientada a objetos, como a
linguagem C++ e Python, possibilitam a implementação da herança múltipla
(TUCKER; NOONAN, 2009).
Na herança simples, uma hierarquia de classe forma uma árvore, com
sua raiz na classe genérica. Uma classe D é uma subclasse de outra classe
C quando ela estende ou especializa o significado da classe C e acrescenta
novas variáveis de instância ou métodos, ou quando modifica as definições
dos métodos público e protegido de C.
A herança múltipla, conforme já mencionado, é um recurso que também
pode ser implementado por algumas linguagens de programação orientada
a objetos. A linguagem Java, por exemplo, uma das linguagens orientada a
objetos mais utilizadas não permite a implementação da herança múltipla.
Em contraposição à herança simples, na herança múltipla uma classe pode
herdar atributos e métodos de mais de uma superclasse, atribuindo a esta
comportamentos de diferentes classes.
3Programação orientada a objetos: herança e polimorfismo
Existem situações em que seu uso pode ser pertinente, mas a herança múl-
tipla também possui desvantagens, especialmente em razão de sua semântica,
que pode dificultar a manutenção do código. Conforme Lima (2014, p. 148)
observa,
[...] uma desvantagem da herança múltipla é que sua semântica se torna muito
complicada em certas circunstâncias. Por exemplo, se uma classe E tem sub-
classes B e C, e um método M é definido diferentemente em B e C, que imple-
mentação de M deveria ser herdada por E: aquela em B, aquela em C ou ambas?
Em alguns casos é necessário que a subclasse possua um comportamento
diferenciado do que foi herdado da superclasse. Na orientação a objetos, cha-
mamos esse conceito de polimorfismo. Na próxima seção, iremos abordá-lo
no contexto da orientação a objetos.
Polimorfismo
O polimorfismo na programação orientada a objetos permite que uma ou mais
classes derivadas de uma mesma superclasse possam invocar métodos que
possuam uma mesma assinatura, mas com comportamentos diferenciados
para cada classe derivada, utilizando, para isso, uma referência a um objeto
da superclasse.
A definição de polimorfismo é mais um dos recursos da orientação a
objetos que possibilita que um comportamento encontrado na realidade seja
aplicado à programação. Na natureza, existem animais que são capazes de
modificar sua forma ou comportamento para atender a determinada situação,
e é isto que o polimorfismo possibilita na programação orientada a objetos.
Segundo Tucker e Noonan (2009, p. 323), “em linguagens orientadas a ob-
jetos, polimorfismo refere-se à ligação tardia de uma chamada a uma ou várias
diferentes implementações de um método em uma hierarquia de herança”.
Para entendermos melhor este exemplo, suponhamos que uma aplicação
implementa um programa de desenho. Em um programa desses, podemos ter
diferentes formas geométricas: círculo, quadrado, retângulo etc.
Programação orientada a objetos: herança e polimorfismo4
Cada uma das formas geométricas é representada, respectivamente, por
uma das classes apontadas a seguir.
� classe circulo;
� classe quadrado;
� classe retangulo.
Todas essas classes são subclasses da classe FormaGeometrica. Temos,
na superclasse FormaGeometrica, a definição do método desenhar,
mas sabemos que desenhar um círculo é diferente de desenhar um retângulo.
Neste caso, a forma de implementar o método desenhar na subclasse
Circulo deve possuir um comportamento diferente da implementação
na subclasse Retangulo, apesar de todas herdarem e necessitarem dessa
implementação. Portanto, o conceito de polimorfismo serve justamente para
resolver questões como esta.
A Figura 3 ilustra um diagrama de classes com base nesta implementação.
Figura 3. Representação de polimorfismo entre classes.
FormaGeometrica
Circulo
desenhar()
Quadrado Retangulo
desenhar()desenhar()
desenhar()
5Programação orientada a objetos: herança e polimorfismo
Para Lima (2014), são dois os tipos mais recorrentes de polimorfismo na
programação orientada a objetos:
a) polimorfismo estático ou sobrecarga de método;
b) polimorfismo dinâmico ou sobrescrita de método.
O polimorfismo estático ou sobrecarga de método é a forma de implemen-
tação em que são definidos vários métodos com o mesmo nome, mas com
assinaturas diferentes. Ou seja, cada método pode receber diferentes parâmetros
ou, então, os mesmos parâmetros de tipos diferentes. A sobrecarga consiste
em permitir, dentro da mesma classe, mais de um método com o mesmo nome.
Entretanto, eles devem necessariamente possuir argumentos diferentes para
funcionar. Booch, Rumbaugh e Jacobson (2006) afirmam que a escolha de
qual método irá ser chamado pelo programa principal dependerá do seu tipo
de objeto, e esta decisão será tomada apenas no tempo de execução, por meio
de ligação tardia.
Veja o exemplo a seguir de um código em linguagem Java para uma classe
Calculadora. Perceba que o método calcula aparece três vezes: o primeiro
recebe como parâmetro dois valores int, o segundo recebe dois valores
double e o terceiro recebe dois valores String.
public class Calculadora {
public int calcula(int a, int b) {
return a+b;
}
public double calcula(double a, double b) {
return a+b;
}
public String calcula(String a, String b) {
return a+b;
}
}
O polimorfismo dinâmico ou sobrescrita de método nos permite reescrever
um método, ou seja, podemos reescrever nas subclasses os métodos criados
inicialmente na superclasse. Os métodos que serão sobrepostos, diferentemente
dos sobrecarregados, devem possuir o mesmo nome, tipo de retorno e quan-
tidade de parâmetros do método inicial. No entanto, este será implementado
Programação orientada a objetos: herança e polimorfismo6
com especificações da classe atual, podendo adicionar algo a mais ou não
(LIMA, 2014).
Para ilustrar este exemplo, vamos novamente utilizar um trecho de código
de uma classe em linguagem Java. Primeiramente, observe a escrita do método
setVelocidade na superclasse Veiculo:
public abstract class Veiculo {
public float velocidade;
public void setVelocidade(float v) {
velocidade = v;
}
}
Veja, então, como ficaria a implementação na subclasse Carro. Observe
que a assinatura do método é a mesma da superclasse, ou seja, recebe v como
parâmetro do tipo float. Porém, na subclasse, além de atribuir o valor de v
para velocidade, são feitos um tratamento e uma atribuição de valor ao atributo
marcha, dependendo da velocidade do veículo.
public abstract class Carro. {
public float velocidade;
public void setVelocidade(float v) {
velocidade=v;
if (velocidade < 20){
marcha = 1;
} else if (velocidade >= 20 && velocidade < 40) {
marcha = 2;
} else if (velocidade >= 40 && velocidade < 60){
marcha = 3;
} else if (velocidade >= 60 && velocidade < 70){
marcha = 4;
} else if (velocidade >= 70){
marcha = 5;
}
}
}
7Programação orientada a objetos: herança e polimorfismo
Na próxima seção, iremos abordar um exemplo de aplicação de herança e
polimorfismo em linguagens orientadas a objetos.
Aplicação de herança e polimorfismo
Nas seções anteriores, abordamos os conceitos de herança e polimorfismo em
programação orientada a objetos, utilizandoa linguagem de programação Java.
Nesta seção, iremos apresentar a implementação destes conceitos na constru-
ção de um programa para uma escola, no qual são utilizados os exemplos de
herança entre as classes Professor e Aluno, que herdam de Pessoa, e o
polimorfismo dinâmico, para o método obterDescontoMensalidade,
que calcula o valor da mensalidade com desconto. A Figura 4 ilustra o modelo
de classes para esta situação.
Figura 4. Modelo de classes para situação proposta de um programa para uma escola.
Pessoa
nome: string
cpf: string
data_nascimento : Date
newAttr : integer
obterDescontoMensalidade(valor)
Professor
salario : double
disciplina : String
Aluno
Matricula : String
Programação orientada a objetos: herança e polimorfismo8
Primeiramente, vamos ver como ficaria a construção da superclasse
Pessoa.
public class Pessoa {
public String nome;
public String cpf;
public Date data _ nascimento;
public Pessoa (String _ nome, String _ cpf, Date _ data) {
this.nome = _ nome;
this.cpf = _ cpf;
this.data _ nascimento = _ data;
}
}
Após a criação da superclasse, vamos verificar os códigos utilizado para
a criação das subclasses Aluno e Professor. Certifique-se de que sua
declaração inclua as palavras extends Pessoa depois de Aluno. Essa
sintaxe é da linguagem Java e significa que as subclasses devem herdar da
superclasse Pessoa.
public class Aluno extends Pessoa {
public Aluno (String _ nome, String _ cpf, Date _ data) {
super ( _ nome, _ cpf, _ data);
}
public String matricula;
}
public class Professor extends Pessoa {
public Professor (String _ nome, String _ cpf, Date _ data) {
super ( _ nome, _ cpf, _ data);
}
public double salario;
public String disciplina;
}
9Programação orientada a objetos: herança e polimorfismo
Podemos verificar que, tanto na subclasse Aluno, quanto na subclasse
Professor, o método construtor está utilizando os atributos que foram
declarados na superclasse Pessoa:
_ nome
_ cpf
_ data
Além disso, observe que no caso da subclasse Aluno é definido um atributo
específico matricula, que só faz sentido para Aluno. No caso da subclasse
Professor, os atributos salario e disciplina só fazem sentido no
contexto de Professor.
Estes exemplos ilustram o típico uso de herança, sem haver necessidade
de reescrever nas subclasses o que é comum a elas, escrevendo somente o
que lhes é específico.
Agora, suponhamos que a escola resolveu criar um programa de oferta
de descontos em mensalidades para Aluno e para Professor. Contudo, a
diferença de percentual seria de 20% para os professores e apenas 10% para
alunos. Vamos adotar o desconto de 10% como o desconto comum, logo, seria
criado na superclasse Pessoa o método obterDescontoMensalidade
para retornar o valor do desconto. Dessa forma, não é necessário fazer nenhuma
alteração na subclasse Aluno, pois o comportamento será automaticamente
herdado da superclasse Pessoa.
public class Pessoa {
public String nome;
public String cpf;
public Date data _ nascimento;
public Pessoa (String _ nome, String _ cpf, Date _ data) {
this.nome = _ nome;
this.cpf = _ cpf;
this.data _ nascimento = _ data;
}
public double obterDescontoMensalidade (double valor) {
//Retorna o valor do desconto na mensalidade
return 0.10 * valor;
}
}
Programação orientada a objetos: herança e polimorfismo10
Como especificado na regra de negócio, os objetos da classe Professor
devem receber um desconto diferenciado de 20%. Logo, utilizando o conceito
de polimorfismo dinâmico, em que o método possui a mesma assinatura,
apenas implementando um novo comportamento, vamos fazer um ajuste para
atender a esta necessidade.
Veja, então, como ficaria a subclasse Professor:
public class Professor extends Pessoa {
public Professor (String _ nome, String _ cpf, Date _ data) {
super ( _ nome, _ cpf, _ data);
}
public double salario;
public String disciplina;
public double obterDescontoMensalidade (double valor) {
//Retorna o valor do desconto na mensalidade
return 0.20 * valor;
}
}
Este foi um exemplo de aplicação simples da utilização em uma mesma
estrutura de classes dos conceitos apresentados neste capítulo. Por fim, é
possível verificar que herança e polimorfismo se relacionam no contexto das
linguagens de programação orientada a objetos.
Acesse o link a seguir para um exemplo de polimorfismo e herança em Python, uma
importante linguagem de programação que permite a orientação a objetos.
https://qrgo.page.link/6xYCs
11Programação orientada a objetos: herança e polimorfismo
BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: guia do usuário. 2. ed. Rio de Janeiro:
Elsevier; Campus, 2006. 474 p.
LIMA, A. S. UML 2.5: do requisito à solução. São Paulo: Érica, 2014. 368 p.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2.
ed. Porto Alegre: AMGH, 2009. 630 p.
Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
Programação orientada a objetos: herança e polimorfismo12
DICA DO PROFESSOR
Existem dois tipos básicos de implementação do conceito de polimorfismo em linguagens
orientadas a objetos. Pode ser usado o formato de implementação estática ou sobrecarga de
métodos ou então o formato de implementação dinâmica ou sobrescrita de método. Qualquer um
dos formatos é encontrado.
Nesta Dica do Professor, você irá entender o conceito de polimorfismo para que seja possível
diferenciar cada um dos seus tipos de implementação.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) Ao analisar um modelo de classes de um sistema, você identificou que existe um
relacionamento de herança entre as classes MeioPagamento e CartaoCredito, sendo a
classe mãe a MeioPagamento e a classe herdeira a CartaoCredito. Sobre essa
situação, assinale a alternativa correta:
A) Somente atributos public da classe MeioPagamento serão herdados pela classe
CartaoCredito.
B) Todos os atributos da classe MeioPagamento serão herdados pela classe CartaoCredito.
C) Todos os atributos serão herdados da classe MeioPagamento, mas os métodos não serão.
D) Todos os atributos serão herdados, mas novos atributos inseridos na classe
MeioPagamento não serão.
E) Não será possível criar um objeto a partir da classe CartaoCredito sem antes criar objeto
MeioPagamento.
2) Utilizando ainda o exemplo do exercício anterior, caso existisse a necessidade de
inserir um atributo para armazenar o valor do limite de gastos diários, que seria
único por CartaoCredito, lembrando que a classe MeioPagamento também tem como
herdeira a classe CartaoDebito, assinale a alternativa correta sobre essa
implementação:
A) O atributo limiteGastosDiario seria criado somente na classe CartaoCredito.
B) O atributo limiteGastosDiario seria criado na classe CartaoCredito e MeioPagamento.
C) O atributo limiteGastosDiario seria criado somente na classe MeioPagamento
D) O atributo limiteGastosDiario seria criado na classe MeioPagamento, CartaoCreditoe
CartaoDebito.
E) O atributo limiteGastosDiario seria criado na classe MeioPagamento e CartaoCredito, mas
os métodos get e set somente na MeioPagamento.
3) Em algumas linguagens de programação orientada a objetos, como C++ e Python, é
possível que uma classe possua relacionamento de herança com mais de uma classe.
Assinale a alternativa correta quanto ao nome desse tipo de herança:
A) Herança Composta.
B) Herança Associativa.
C) Herança Dupla.
D) Herança Múltipla.
E) Herança Binária.
4) Em herança entre classes, existe a possibilidade de uma classe herdeira reescrever
um método implementado pela classe mãe. Dessa forma, a classe herdeira atribui um
comportamento diferenciado ao da classe mãe, sendo o nome desse conceito
polimorfismo. Assinale a alternativa correta sobre o polimorfismo:
A) Só é possível aplicar polimorfismo quando os métodos têm a mesma assinatura.
B) O polimorfismo é um recurso mais recente que a herança na orientação a objetos.
C) Em herança múltipla, não é possível aplicar o conceito de polimorfismo, apenas em
herança simples.
D) O polimorfismo só permite a alteração de escopo de um método da superclasse pela
subclasse.
E) O polimorfismo é uma característica em orientação a objetos que usa a hierarquia de
objetos.
5) Existem duas formas de implementação de polimorfismo. Uma se dá quando se tem a
mesma operação implementada várias vezes na mesma classe e a outra acontece na
herança, quando a classe herdeira altera o método original. Assinale a alternativa
correta quanto ao nome desses tipos de implementação de polimorfismo:
A) Sobrecarga e Sobreposição.
B) Estático e Sobrecarga.
C) Dinâmico e Sobreposição.
D) Alternativo e Sobrecarga.
E) Alternativo e Sobreposição.
NA PRÁTICA
A herança, o polimorfismo e a reutilização de código estão relacionados em programação
orientada a objetos. Quando se fala de herança entre classes, fala-se implicitamente de
reutilização de código, pois herdar é minimizar a escrita de código. O polimorfismo entra como
recurso interessante que permite que apenas aqueles métodos que devem se comportar de forma
diferenciada em uma classe herdeira sejam reescritos sem a necessidade de reescrita total de
uma classe.
A herança é um conceito muito poderoso, uma vez possibilitar que os desenvolvedores
maximizem o uso dos métodos (comportamento) e dos dados (estrutura) dos objetos existentes.
Já o polimorfismo é a habilidade de objetos receberem a mesma mensagem e comportarem-se
de maneira diferente.
Neste Na Prática, você verá um exemplo da utilização de herança e polimorfismo em uma
aplicação escrita em Java para entender como esses conceitos se relacionam com o objetivo de
reduzir a necessidade de reescrita de código.
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Herança na programação orientada a objetos
Neste vídeo, você entenderá, de forma bem didática, sobre o conceito de herança na
programação orientada a objetos.
Conteúdo interativo disponível na plataforma de ensino!
Conceituando polimorfismo
Para conhecer mais sobre o conceito de polimorfismo na programação orientada a objetos,
assista ao vídeo a seguir.
Conteúdo interativo disponível na plataforma de ensino!
Herança Múltipla com Python
Assista ao vídeo a seguir e conheça a aplicação do conceito de Herança Múltipla, utilizada na
linguagem de programação Python.
Conteúdo interativo disponível na plataforma de ensino!
Programação orientada a objetos:
interfaces e classes abstratas
APRESENTAÇÃO
Na programação orientada a objetos (POO), a relação de herança e reúso entre classes é um
princípio básico. Dentro desse conceito, a definição de classes abstratas serve como um modelo
para outras classes herdeiras, garantindo, assim, que as classes que a herdem implementem
alguns dos seus métodos. Outra importante definição são as classes interfaces, estas determinam
um padrão com um conjunto de métodos que, obrigatoriamente, devem ser definidos pelas
classes que a implementam, muito similar a um contrato entre classes.
Nesta Unidade de Aprendizagem, você vai entender melhor a definição de classes abstratas e
interfaces em programação orientada a objetos, e saber quando usar um ou outro recurso.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Explicar o que são interfaces.•
Identificar classes abstratas.•
Aplicar interfaces e classes abstratas em programação orientada a objetos (POO).•
DESAFIO
A utilização de interfaces em linguagens de programação orientada a objetos é um recurso muito
benéfico em determinadas situações. Por meio da utilização de interfaces é possível determinar
uma obrigação de definição de métodos por classes que implementem as interfaces, garantindo,
assim, que, dentro de um contexto, as classes se comportem com uma determinada similaridade
esperada.
Com base nisso, imagine a seguinte situação:
Fazendo uso do conceito de interfaces, descreva em formato textual e também apresente o
modelo de classes:
a) Como ficaria o escopo da interface chamada LoginPortal.
b) O escopo de uma das classes que a implementa, chamada SistemaMarketing, que também
tem o atributo codigoColaborador.
INFOGRÁFICO
As classes abstratas têm uma importância em programação orientada a objetos e a sua utilização
é recomendada em algumas situações. Como profissional, é importante entender e saber para
que servem as classes abstratas e quando é recomendado o seu uso.
Neste Infográfico, você terá um resumo do que são classes abstratas e as suas características,
visando, assim, a facilitar o seu entendimento de quando se deve utilizá-las.
Conteúdo interativo disponível na plataforma de ensino!
CONTEÚDO DO LIVRO
Entender as diferenças e as utilidades das interfaces e classes abstratas para a programação
orientada a objetos é importante no contexto de reusabilidade e organização do código de um
sistema. As interfaces possibilitam que sejam criados protocolos a serem implementados por
classes em programação orientada a objeto.
Classes abstratas possibilitam que uma classe padrão, com métodos genéricos,
seja implementada e somente os específicos sejam necessários na implementação em classes
derivadas, criando uma espécie de classe padrão em um contexto específico, facilitando, e
muito, a manutenção.
No capítulo Programação orientada a objetos: interfaces e classes abstratas, da obra Paradigmas
de programação, você vai entender mais sobre o conceito de classes abstratas e interfaces do
ponto de vista de programação orientada a objetos.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação orientada
a objetos: interfaces
e classes abstratas
Objetivos de aprendizagem
Ao final deste texto, você deverá apresentar os seguintes aprendizados:
� Definir o que são interfaces.
� Identificar classes abstratas.
� Aplicar interfaces e classes abstratas em programação orientada a
objetos.
Introdução
O conceito de herança é fundamento básico em orientação a objetos,
sendo praticamente impossível dissociar orientação a objetos e reuso de
código do conceito de herança entre classes. A necessidade da herança
entre classes trouxe outras necessidades que poderiam facilitar o trabalho
de programadores em linguagens orientadas a objetos.
Criar um padrão que fosse utilizado e seguido pelas classes que her-
dam outra classe ou, então, garantir a implementação de determinados
métodos por classes que fazem parte de um determinado contexto, são
possibilidades alcançadas devido à utilização dos conceitos de classes
abstratas e interfaces.
Neste capítulo, abordaremos as interfaces no contexto de orientação
a objetos. Além disso, aprenderemos a identificar classes abstratas e
veremos algumas aplicações práticas.
Interfaces na programação orientada a objetos
As interfaces definem uma linha entre a especificação do queuma abstração
realiza e a implementação do modo como será realizada. Uma interface se
caracteriza por ser uma coleção de operações utilizadas para especificar uma
espécie de “contrato” com a classe que irá implementá-la.
Segundo Booch, Rumbaugh e Jacobson (2006, p. 156), “uma interface
é uma coleção de operações empregadas para especificar o serviço de uma
classe ou componente”. Ao realizarmos a declaração de uma interface em
uma linguagem de programação orientada a objetos, estamos estabelecendo
o comportamento esperado de uma classe independente que implemente esta
interface, garantindo que todos os métodos que foram definidos na interface
sejam obrigatoriamente implementados por esta classe.
Algumas linguagens de programação, como C#, Java e Python, têm suporte
para o conceito de interfaces, que são importantes não apenas por dividir a
especificação e a implementação de uma classe ou componente; à medida
que desenvolvermos sistemas de maior porte, as interfaces serão úteis para
especificar a visão externa de um pacote ou subsistema, por exemplo.
Uma interface pode ser descrita como uma classe estereotipada para expor
suas operações e outras propriedades. Para mostrar o relacionamento entre
uma classe e suas interfaces é fornecida uma notação especial (LIMA, 2014).
A Figura 1 mostra um exemplo de uma classe interface que representa o tipo
Pessoa e os métodos necessários para que classes no contexto de um sistema
de gestão de documentos implementem para diferentes tipos de pessoas que
acessam a plataforma.
Figura 1. Representação de interface em programação orientada a objetos.
<<interface>>
Pessoa
adicionar()
excluir()
pesquisar()
Programação orientada a objetos: interfaces e classes abstratas2
Para fazer uma analogia, podemos dizer que, quando uma classe implementa
uma interface, a classe “assina um contrato” com esta, se comprometendo,
assim, a implementar seus métodos. Em troca, os objetos instanciados a partir
dessa classe podem ser classificados como do tipo definido pela interface.
Uma característica interessante do uso de interfaces em programação
orientada a objetos é que uma classe pode implementar várias interfaces e,
assim, em algumas linguagens em que o conceito de herança múltipla não
existe, possibilita que este seja de certa forma alcançado.
Interfaces não podem implementar nenhum método, elas apenas definem
os métodos e suas assinaturas. A implementação destes é responsabilidade
das classes que a implementam ou “assinam contrato” com esta. Isso permite
que você obedeça a alguns dos princípios de reuso e escreva códigos pouco
acoplados e com alta coesão (DEITEL; DEITEL, 2010).
Interfaces são ferramentas importantes em linguagens de programação
orientada a objetos, melhorando a qualidade de seu código quando bem uti-
lizadas. Permitem um encapsulamento de comportamento, ocultando qual
classe está realizando uma tarefa específica, e isto só é possível porque a
classe que implementa uma interface é obrigada a seguir o protocolo definido
nesta. Dessa forma, as principais vantagens de seu uso são uma manutenção
mais simples do código e um maior reuso deste, aproveitando os benefícios
da programação orientada a objetos da melhor forma.
O desenvolvimento do código voltado para interfaces se deu a partir da necessidade de
se organizar as classes de forma mais coesa, com baixo acoplamento e funcionalidades
bem encapsuladas (fundamentos da orientação a objeto).
Se o programador implementa uma interface em uma classe e deixar de
especificar um método desta, um erro será gerado. Dessa forma, a utilização
de interfaces traz um grande benefício em casos em que é necessária a garantia
de que os métodos serão implementados.
3Programação orientada a objetos: interfaces e classes abstratas
Contudo, outro recurso utilizado em programação orientada a objetos
que, muitas vezes, gera certa confusão com o conceito de interfaces, são as
classes abstratas. Classes abstratas também são utilizadas para resolver ques-
tões em que é necessária a implementação de métodos por classes herdeiras.
No entanto, estas classes possuem diferenças em relação às interfaces. Na
próxima seção, iremos definir o que são classes abstratas no conceito de
programação orientada a objetos.
Classes abstratas
Ao criarmos uma classe, na maioria das vezes o fazemos para atender a um
determinado propósito, sem nos preocuparmos se a classe poderá ser herdada
por outras. No entanto, em alguns casos, ao criarmos uma classe já temos ideia
de que esta poderá ser herdada por outras, ou seja, já temos a certeza prévia
da necessidade de herança.
Nesse conceito, a criação de classes abstratas faz sentido, pois estas são
utilizadas para definir um tipo que será seguido pelas classes herdeiras.
Às vezes é útil declarar classes — chamadas classes abstratas — para as
quais você nunca pretende criar objetos. Como elas são usadas somente como
superclasses em hierarquias de herança, são chamadas superclasses abstratas.
Essas classes não podem ser usadas para instanciar objetos, pois são incom-
pletas. Suas subclasses devem declarar as partes ausentes para se tornarem
classes concretas, a partir das quais você pode instanciar objetos (DEITEL;
DEITEL, 2010, p. 309).
As classes que não são abstratas e herdam classes abstratas são denominadas
classes concretas. Sobre as classes abstratas, podemos destacar os seguintes
conceitos.
� Uma classe abstrata serve como modelo para uma classe concreta.
� Como são apenas modelos, não podem ser instanciadas diretamente.
� Por não ser instanciadas, devem ser herdadas por classes concretas.
� Uma classe abstrata pode, ou não, conter métodos abstratos, ou seja,
pode ou não implementar um método.
� Contudo, métodos abstratos definidos em uma classe abstrata devem,
obrigatoriamente, ser implementados em uma classe concreta.
Programação orientada a objetos: interfaces e classes abstratas4
De acordo com Lima (2014, p. 334),
[...] as classes abstratas não podem ser utilizadas nas expressões de instanciação
de classes. Apesar de não poderem participar em expressões de instanciação,
as classes abstratas podem definir construtores. Os construtores de classes
abstratas são responsáveis pelas iniciações que podem ser necessárias para
os campos que podem ser utilizados nas implementações dos métodos. Assim
uma subclasse direta ou indireta de uma classe abstrata ao ser instanciada
pode causar a execução de um construtor da classe abstrata.
A Figura 2 ilustra o exemplo de uma classe abstrata chamada BombaDe-
Succao, com a definição do método abstrato ativa e a herança pelas classes
BombaDiesel e BombaDAgua com a redefinição do método abstrato.
A forma de ligar uma bomba de sucção a diesel é bem diferente da forma
como se liga uma bomba de sucção de água.
Figura 2. Representação de uma classe abstrata.
Fonte: Dias (2007, p. 2).
BombaDeSuccao
BombaDiesel BombaDAgua
rede�nição rede�nição
As classes abstratas possuem similaridades com as interfaces, pois também
são utilizadas como uma espécie de “contrato” a ser implementado pelas
classes herdeiras. Todavia, é importante saber diferenciar que uma classe
abstrata, como o nome sugere, se trata de uma classe, e as interfaces são
consideradas entidades.
5Programação orientada a objetos: interfaces e classes abstratas
Classes abstratas também podem possuir outros métodos que não são
abstratos e, nesse caso, não é obrigatória sua implementação pelas classes
herdeiras. Uma classe abstrata pode ter métodos não abstratos e atributos não
estáticos, o que não pode ser feito com uma interface. Portanto, com uma classe
abstrata você pode criar todo o algoritmo da classe e deixar somente um ou
mais métodos específicos para ser implementados nas subclasses (BOOCH;
RUMBAUGH; JACOBSON, 2006). Contudo, a principal diferença é que uma
classe abstrata é uma classe como outra qualquer e, sendo assim, participa de
uma hierarquia de classes. Dessa forma, uma subclasse de uma classeabstrata
só pode estender essa classe abstrata, não podendo estender duas classes, por
exemplo, enquanto no caso das interfaces podem ser implementadas quantas
forem preciso, já que estas não participam da hierarquia de classes.
As classes abstratas podem não ter todos os seus métodos declarados como
métodos abstratos, mas uma classe, para ser considerada abstrata, necessita
ter pelo menos um método em seu escopo declarado como método abstrato.
Para entender melhor esse conceito, imaginemos uma conta bancária e que
toda a classe que representa esta conta deve ter uma forma de sacar. No entanto,
dependendo do tipo de conta do cliente, pode ser necessária a implementação
de diferentes formas de sacar.
Por exemplo, um cliente que possui uma conta especial pode realizar
saques acima do saldo disponível em sua conta, enquanto um cliente comum
não tem esse direito. Nesse contexto, podemos definir, na classe Conta, um
método abstrato sacar. Assim, toda classe que herdar de Conta deverá
sobrescrever (lembra-se do conceito de polimorfismo dinâmico) esse método,
implementando suas próprias regras de saque.
Na classe Conta, o método sacar seria definido somente com a assinatura,
sem corpo, conforme o exemplo a seguir, escrito em Java:
public abstract boolean sacar (double valor);
Esse método não define como o saque será executado, apenas pela decla-
ração de abstract, que obriga que todas as classes que herdam de Conta
implementem esse método. A Figura 3 ilustra o modelo de classes que repre-
sentam a herança da classe abstrata Conta.
Programação orientada a objetos: interfaces e classes abstratas6
Figura 3. Modelo de classes do exemplo Conta.
Conta
sacar(valor)
ContaEspecial
sacar(valor)
ContaPoupança
sacar(valor)
Uma classe abstrata é um conjunto de informações a respeito de uma coleção de
outras classes. Sozinha, ela não tem utilidade, já que não podemos instanciar um objeto
desta classe, apenas instanciar objetos de classes que estendem a classe abstrata inicial.
Ela serve somente para simplificar o sistema, juntando, em um único lugar, diversas
características que são comuns a um grupo de classes.
Portanto, como visto, jamais será possível criarmos um objeto a partir de
uma classe abstrata, pois se faz necessário a herança dessa classe por uma
classe concreta e os objetos devem ser instanciados somente a partir da classe
concreta. As classes abstratas são recursos valiosos quando não é possível
utilizar interfaces em razão de que nem todos os métodos serão implemen-
tados. Dessa forma, é possível que os métodos genéricos, aqueles que terão
um comportamento igual em todas as classes herdeiras, sejam definidos na
classe abstrata. Aqueles que podem sofrer comportamentos específicos ficam
por conta de implementações em classes herdeiras. Essa é a questão que deve
ser considerada ao se tomar a decisão de utilizar uma classe abstrata ou optar
por outro recuso. Na próxima seção, veremos alguns exemplos de aplicação
de classes abstratas e interfaces em programação orientada a objetos.
7Programação orientada a objetos: interfaces e classes abstratas
Aplicação de interfaces e classes abstratas
Nas seções anteriores, abordamos os conceitos de interface e classes abstratas
em programação orientada a objetos. Nesta seção, veremos, a aplicação prática
dos conceitos explorados neste capítulo, utilizando um exemplo criado em
outra linguagem de programação, C#.
Primeiramente, vamos criar uma classe abstrata Forma, com a criação
de um método abstrato chamado CalcularArea e mais dois métodos, que
não são declarados como abstratos.
public abstract class Forma
{
private double _ area;
public double Area
{
get
{
return _ area;
}
set
{
_ area = value;
}
}
public abstract void CalcularArea();
public string Descricao()
{
return "Sou a classe abstrata Forma.";
}
}
Agora, vamos criar a classe Quadrado, que herda a classe abstrata Forma.
Na sintaxe de C#, a herança é representada pelo nome da subclasse, seguido
por : e o nome da superclasse. Observe, no trecho de código a seguir, que
o método abstrato calcularArea é definido nesta classe. Isso ocorre em
C# pela declaração do comando override, que significa que o método
sobrescreve o método abstrato herdado.
Programação orientada a objetos: interfaces e classes abstratas8
public class Quadrado : Forma
{
private double lado;
public double Lado
{
get
{
return lado;
}
set
{
lado = value;
}
}
public override void CalcularArea()
{
this.Area = lado * lado;
}
}
Agora, verificamos a declaração de duas interfaces em C#. A primeira é a
interface IAcao, que define que as classes que vão implementar essa interface
devem definir o método Desenhar, e a segunda interface é IAcabamento,
que define que as classes que a implementam necessitam definir o método
Pintar.
public interface IAcao
{
void Desenhar();
}
public interface IAcabamento
{
void Pintar();
}
9Programação orientada a objetos: interfaces e classes abstratas
Na sequência, vamos criar a classe ExemploInterface, que irá imple-
mentar as interfaces IAcao e IAcabamento. Perceba que a sintaxe em C#
é igual a de herança que utilizamos no exemplo anterior de classe abstrata.
No entanto, com interfaces é possível implementar mais de uma interface,
como no exemplo a seguir.
public class ExemploInterface : IAcao, IAcabamento
{
public void Desenhar()
{
Console.WriteLine("Implementação do metodo Desenhar
da interface Acao");
}
public void Pintar()
{
Console.WriteLine("Implementação do metodo Pintar da
interface Acabamento");
}
}
Com esses exemplos simples aplicamos, de forma didática, os conceitos
de herança de classe abstrata e a definição e a implementação de interfaces.
A sintaxe dos comandos pode variar conforme a linguagem de programação
utilizada, como vimos entre os exemplos acima, em C#, e alguns exemplos
anteriores que utilizavam a linguagem Java. O importante é perceber que
as características para cada conceito, conforme mencionado, se mantém.
Classes abstratas e interfaces são conceitos essenciais para quem trabalha
com linguagens de programação orientada a objetos.
O link a seguir mostra exemplos de polimorfismo, classes abstratas e interfaces, fun-
damentos da programação orientada a objetos em Java.
https://qrgo.page.link/X5z9a
Programação orientada a objetos: interfaces e classes abstratas10
BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: guia do usuário. 2. ed. Rio de Janeiro:
Elsevier; Campus, 2006. 474 p.
DEITEL, P.; DEITEL, H. Java: como programar. 8. ed. São Paulo: Pearson, 2010. 1144 p.
DIAS, Z. Classes Abstratas. Campinas: Instituto de Computação, Universidade Estadual
de Campinas, 2007. 17 p. (Notas de aula da disciplina MC336/MC346 – Paradigmas de
Programação). Disponível em: http://www.ic.unicamp.br/~zanoni/mc336/2012-2s/java/
Transparencias/1%20por%20pagina/cap04-4.pdf. Acesso em: 5 out. 2019.
LIMA, A. S. UML 2.5: do requisito à solução. São Paulo: Érica, 2014. 368 p.
Leituras recomendadas
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
11Programação orientada a objetos: interfaces e classes abstratas
DICA DO PROFESSOR
Alguns termossão utilizados diariamente por profissionais de programação que trabalham com
programação orientada a objetos. Dentre esses termos, é comum se ouvir falar de classes
abstratas e interfaces. Mas apesar de terem algumas similaridades, esses dois conceitos têm
também diferenças. Você sabe quais são as diferenças e as similaridades entre classes abstratas e
interfaces?
Na Dica do Professor, vamos apresentar as diferenças e as similaridades entre as classes
abstratas e as interfaces do ponto de vista da orientação a objetos.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) As classes abstratas são classes que determinam um tipo, são como uma espécie de
rascunho de como as classes que a implementam devem se comportar.
Sobre os conceitos de uma classe abstrata, assinale a alternativa correta:
A) Classes abstratas devem definir todos os seus métodos como abstratos.
B) Classes abstratas não permitem a utilização de polimorfismo pelas classes herdeiras.
C) Classes abstratas não podem ser instanciadas.
D) Classes abstratas obrigam a implementação de todos os seus métodos.
E) Classes abstratas são um tipo especial de encapsulamento, pois não é possível saber a sua
implementação.
Outras questões são também importantes ao considerar o conceito de classes 2)
abstratas. Analise as afirmativas a seguir e assinale aquela que está correta acerca
dos conceitos de classes abstratas.
A) Uma classe abstrata pode herdar de outra classe abstrata.
B) Um método abstrato é um método que tem implementação na classe abstrata.
C) A classe abstrata não pode ser considerada uma superclasse, pois não contém instâncias.
D) Uma classe abstrata também não pode conter métodos construtores.
E) Cada uma das classes derivadas não completa a funcionalidade da classe abstrata.
3) Classes abstratas têm um significado diretamente ligado ao conceito de herança. São
classes que não fazem sentido sem que exista uma relação de herança de outras
classes com a classe abstrata.
Em relação a essa afirmativa, marque a alternativa correta sobre a relação entre
classes abstratas e herança na orientação a objetos:
A) As classes abstratas permitem estender o conceito de herança múltipla nas linguagens.
B) Assim como na herança, classes abstratas possibilitam que os métodos genéricos sejam
especificados somente em classes derivadas.
C) Classes abstratas são declaradas da mesma forma que é declarada a superclasse em
herança.
D) As classes abstratas impedem que a instância de objetos seja a partir da classe genérica.
Diferentemente de herança, não é possível acrescentar novos métodos após uma herança E)
em classes abstratas.
4) As interfaces em programação orientada a objetos são outro recurso importante e
que, dependendo do contexto, possibilita algumas vantagens se comparado ao uso de
classes abstratas.
Uma das principais vantagens da utilização de interfaces está relacionada ao fato de
que:
A) As interfaces não obrigam a implementação de todos os métodos pelas classes que as
implementam.
B) As interfaces otimizam o uso de memória em relação às classes abstratas, pois não são
alocadas sem uso.
C) As interfaces permitem que sejam instanciados objetos a partir dessa diferença de classes
abstratas.
D) As interfaces possibilitam criar um tipo de classe padrão que todas as derivadas devem
seguir.
E) A vantagem principal das interfaces é que não há limites de quantas interfaces uma classe
pode implementar.
O seguinte trecho de código em linguagem de programação Java especifica uma
interface para classes que implementem um tipo de FiguraGeometrica:
public interface FiguraGeometrica
{
public String getNomeFigura();
public int getArea();
public int getPerimetro();
}
5)
Assinale a alternativa que contém uma afirmativa correta sobre o trecho
apresentado:
A) As classes podem conter diferentes implementações dos métodos de FiguraGeometrica.
B) Nenhuma classe tem a obrigação de implementar todos os métodos de FiguraGeometrica
por serem get.
C) As classes que implementam a interface podem conter diferentes assinaturas dos métodos.
D) As classes só implementam um tipo de interface de FiguraGeometrica, mesmo que existam
outras.
E) As classes que herdam, implementam todos os métodos da interface com o mesmo escopo.
NA PRÁTICA
Nesta Unidade de Aprendizagem, foi possível entender a importância e a utilidade de interfaces
em programação orientada a objetos. Java é uma linguagem amplamente utilizada e que
implementa o paradigma de orientação a objetos.
Na Prática, você verá a implementação em Java de uma classe abstrata Eletrodomestico para ser
utilizada como modelo para implementação dos diferentes tipos de eletrodomésticos, neste caso,
uma TV e um rádio.
Conteúdo interativo disponível na plataforma de ensino!
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Interfaces com linguagem de programação Java
No vídeo a seguir, confira um exemplo de utilização de interfaces com a linguagem de
programação orientada a objetos Java.
Conteúdo interativo disponível na plataforma de ensino!
Aula sobre interfaces e classes abstratas
Confira, a seguir, uma videoaula bem interessante que aborda os conceitos de interfaces e
classes abstratas explorados nesta Unidade de Aprendizagem.
Conteúdo interativo disponível na plataforma de ensino!
Interface ou classe abstrata
Neste conteúdo, veja um comparativo breve e útil sobre a diferença entre interface e classe
abstrata.
Conteúdo interativo disponível na plataforma de ensino!
Programação orientada a objetos: Java,
C++ e C#w
APRESENTAÇÃO
Assim como a linguagem natural, que permite expressar por meio da fala os anseios, os
sentimentos e os objetivos, a linguagem de programação surgiu para que fosse possível
padronizar a comunicação de instruções para um computador. Por meio dela, o programador
especifica precisamente onde o computador vai atuar, o que ele vai armazenar e transmitir a
partir dos comandos do usuário.
A competitividade do mercado atual exige um conhecimento funcional muito elevado por parte
dos desenvolvedores. De acordo com a comunidade de programação TIOBE, que avalia a
popularidade das linguagens de programação, as linguagens Java, C e C++ foram as três
linguagens mais populares no ano de 2008. De lá para cá, diversas outras surgiram, inclusive a
C#, que é uma continuação da C++, com melhorias voltadas para performance e experiência do
usuário, o que não extingue a importância das três mencionadas anteriormente, tendo em vista
características importantes que as fazem continuar entre as mais funcionais e robustas no
mercado do desenvolvimento (SEBESTA, 2011, p. 24).
Nesta Unidade de Aprendizagem, você irá conhecer as linguagens de programação Java e as
suas características e também irá acompanhar a análise e o funcionamento das linguagens C++ e
C#.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Identificar as principais características da linguagem Java.•
Analisar a Linguagem C++.•
Descrever a linguagem C# e as suas particularidades.•
DESAFIO
No paradigma orientado a objetos, diz-se que uma classe é uma descrição cuja função é abstrair
objetos e comportamentos, e que poderá ser herdada dentro do código por outras classes. Ela
descreve o tipo de serviço e objetos a serem armazenados na memória.
Analise a situação a seguir:
Considerando que todos os atributos da classe Dados_Aluno deverão ser acessados por getters e
setters, como você apresentaria o código?
INFOGRÁFICO
Java é uma linguagem de programação orientada a objetos criada por um grupo de engenheiros
na década de 1990. No ano de 2008, ela foi adquirida pela empresa Oracle e, atualmente, é a
linguagem mais utilizada entre os desenvolvedores, pois Java não é apenas uma linguagem, ela é
uma plataforma, ou seja, um ambiente computacional que permiteo desenvolvimento de
aplicações na linguagem Java.
Neste Infográfico, veja algumas características traduzidas para um fácil entendimento dessa
importante linguagem de programação.
CONTEÚDO DO LIVRO
As linguagens de programação, de um modo geral, expressam de forma escrita instruções que
precisam ser realizadas pelo computador. Cada uma é apropriada para determinados tipos de
aplicação, permitindo que cada vez mais problemas sejam resolvidos por meio desse tipo de
construção. Quando uma nova linguagem surge, é muito comum que os seus criadores tenham
se baseado em uma linguagem já existente para essa nova construção. Isso aconteceu com o
Java e o C#, que se valeram da linguagem C e C++ para criá-las.
No capítulo Programação orientada a objetos: Java, C++ e C#w, da obra Paradigmas de
programação, você estudará sobre essas três linguagens, o que permitirá que você tenha uma
pequena noção desse vasto universo, trazendo o conhecimento e a curiosidade para você dar
continuidade na busca do conhecimento no que diz respeito ao desenvolvimento de sistemas.
PARADIGMAS DE
PROGRAMAÇÃO
Marcia Cristina Domingues Leite
Programação orientada a
objetos: Java, C++ e C#
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Identificar as principais características da linguagem Java.
� Analisar a linguagem C++.
� Descrever a linguagem C# e suas particularidades.
Introdução
De modo geral, uma linguagem de programação (LP) é um conjunto de
regras sintáticas e semânticas que definem o que um computador deverá
fazer. Historicamente, a primeira LP para computadores pessoais (chamada
linguagem de alto nível) foi Fortran, criada em 1954. Desde então, muitas
outras linguagens surgiram, algumas ainda continuam sendo utilizadas,
pois suas características as mantêm no mercado do desenvolvimento por
fatores como segurança, multiplataformas, tipagem e orientação a objetos
(OO). Outras, deram origem ou influenciaram as linguagens conhecidas
atualmente. A linguagem C, por exemplo, influenciou linguagens como
Java e C#. Esta última, incorpora a OO à linguagem C que, por sua vez, é
basicamente procedural, baseada em rotinas, métodos e funções.
Neste capítulo, você conhecerá um pouco sobre essas três impor-
tantes LPs, suas características, particularidades e de que forma elas
influenciaram grande parte das linguagens de programação utilizadas
hoje no mercado mundial de desenvolvimento.
Paradigma da orientação a objetos
Machado, Franco e Bertagnolli (2016) explicam que a OO trata de conceitos cujo
objetivo principal é a resolução de problemas por meio da sua decomposição
em partes menores, utilizando métodos como abstração e modularização.
Quando os primeiros computadores surgiram, buscava-se uma maior
eficiência, sem que isso tomasse grande parte da memória, em razão das
limitações de hardware daquela época. Os programadores da época dividiam
seus programas em blocos, de modo a realizar essa economia de recursos.
A partir disso, foram criadas técnicas para resolução de problemas, divi-
dindo um grande problema em diversos problemas menores. Essa técnica é
realizada por meio da modularização, que permite resolver e entender proble-
mas complexos e reutilizar códigos. Para que se possa a OO é importante saber
que esse tipo de programação atende a quatro aspectos principais, descritos
nos itens a seguir.
Abstração
É o aproveitamento de aspectos relevantes de cada um dos “problemas” resol-
vidos dentro de um código. Portanto, cada módulo representa uma abstração
existente no todo do problema.
Sabemos que a OO trata de representações de um objeto real, mas é im-
portante entender o que esse objeto irá realizar nessa abstração. Em geral,
objeto é a representação de algo que existe. No desenvolvimento, os objetos
possuem as seguintes características: identidade, estado e comportamento.
Encapsulamento
Dentro do contexto da OO, o encapsulamento é utilizado a todo momento,
conforme se trabalha com propriedades e métodos de alguns componentes, sem
ver como está implementado. Um exemplo disso é a utilização de application
programming interface (API), utilizadas para requisitar informações sobre
uma página Web, por exemplo, ou um banco de dados.
Grande parte das linguagens que utilizam a OO encapsulam seu código em
propriedades privadas, com métodos chamados getters e setters. Esses métodos,
respectivamente, retornam e definem o valor da propriedade adicionando uma
camada de segurança à aplicação, evitando, assim, o acesso direto ao objeto.
Programação orientada a objetos: Java, C++ e C#2
Métodos nada mais são do que instruções que damos ao objeto, por exemplo:
criar um cliente. Na prática, os métodos get ou set trabalham da seguinte forma:
a aplicação faz uma requisição utilizando qualquer um deles. Por exemplo, um
usuário busca seu cadastro em determinada aplicação, como isso é feito não
pode ser visualizado, mas está acontecendo por trás da interface.
Herança
Permite que se utilize uma classe com suas propriedades e métodos, incluindo
outras propriedades e métodos existentes em outra classe que está sendo criada.
A herança é uma das grandes vantagens da programação OO, pois ela
otimiza em muito o projeto do software, tanto no que diz respeito ao tempo,
como em linhas de código.
Polimorfismo
Podemos tratar um objeto A que herdou características de outro objeto B como
se ele fosse o próprio objeto B, ou seja, um objeto pode se comportar como se
fosse outro objeto, do qual ele herdou atributos e métodos. Toda e qualquer
alteração de um método herdado de um objeto pai caracteriza o polimorfismo.
Outro aspecto importante em OO, é que algumas partes do objeto são
privadas e outras, públicas. Geralmente, utiliza-se métodos públicos na in-
terface do usuário.
No escopo de um software, a classe descreve que propriedades ou atributos
o objeto terá. A definição de uma classe descreve o comportamento que o
objeto terá e de que forma ele funcionará na aplicação.
� Atributos: são propriedades que compõe uma classe, como nome, tipo,
valor e visibilidade (público, privado ou protegido).
� Métodos: são as funcionalidades da classe, como nome, tipo, argumentos
e visibilidade.
A Figura 1 demonstra a construção de uma classe bem como a declaração
de variáveis dentro dela.
3Programação orientada a objetos: Java, C++ e C#
Figura 1. Exemplo de classe em Java.
Linguagem Java e seu histórico
Historicamente, a LP Java foi criada em 1991 pelos engenheiros da Sun
Microsystems, que tinham como missão criar uma linguagem que pudesse ser
utilizada em pequenos equipamentos domésticos, como telefones, geladeiras,
controles de TV, etc. A intenção era que esses aparelhos pudessem se comunicar
entre si (MACHADO; FRANCO; BERTAGNOLLI, 2016).
Com o advento da World Wide Web (WWW), os engenheiros da Sun
passaram a investir em novos conceitos para essa linguagem, que atualmente
lidera o ranking das LP mais utilizadas no mundo do desenvolvimento.
A LP Java é OO, e os programas são compilados, interpretados e trans-
formados em uma linguagem intermediária chamada bytecode. O bytecode
é multiplataforma e passa por um interpretador Java todas as vezes que o
programa é executado. Isso se deve em razão da máquina virtual Java vir-
tual machine (JVM) que permite que todos os produtos consigam executar
programas em Java, basta que a plataforma possua a JVM.
A Figura 2 demonstra com a JVM funciona na execução dos programas
em Java nas mais diversas plataformas.
Programação orientada a objetos: Java, C++ e C#4
Figura 2. JVM.
Fonte: Adaptada de DreamStockIcons/Shutterstock.com.
Class OláMundo{
public static void main (string args){
system.out.printin(*Olá Mundo!*)
}
}
Programa Java Compilador JVM
JVM
JVM
Olá
Mundo!
Olá
Mundo!
Olá
Mundo!
MacOS
Android
Windows
Linguagem C++
No escopo da programação, a linguagem C++ é uma evolução da linguagem
C e, assim como a primeira, influencioumuitas outras linguagens presentes
no dia a dia dos usuários, desde a linguagem JavaScript que é executada no
navegador a cada página acessada, ou ainda na linguagem Java que é executada
nos smartphones. Muitas linguagens que são utilizadas hoje foram construídas
com C++ no que se refere à sintaxe ou ao compilador.
A linguagem C++ é composta por bibliotecas estáveis, que servem de base
para diversas outras linguagens. Sua influência pode ser notada nos maiores
sistemas operacionais e programas do mundo, o que permite concluir que
entender a linguagem C++ é o primeiro passo para entender muitas outras
linguagens atuais.
Horstmann (2005) explica que a linguagem C++ ultrapassou a linguagem C
com o acréscimo da programação OO e não procedural, como era C. Ele explica
também que a linguagem C++ é sensível a letras maiúsculas e minúsculas,
entretanto, espaços e quebras de linha não fazem diferença na estrutura do
código, podendo o programa ser escrito em uma única linha. Outro detalhe
importante é que cada linha de comando precisa terminar em ponto e vírgula,
caso contrário o código não irá rodar.
5Programação orientada a objetos: Java, C++ e C#
A seguir, veja algumas das características da linguagem C++.
� Melhoramento da linguagem C — a linguagem C++ é uma continuação
da linguagem C, com melhorias e novos recursos que otimizaram ainda
mais a linguagem.
� Estaticamente tipada — nesse caso é necessário definir o tipo de cada
variável de forma explícita. Por exemplo, caso seja necessário declarar
uma variável que irá armazenar números, é preciso dizer que é do tipo
inteiro (int); ou se a variável for armazenar caracteres, será necessário
dizer que ela é do tipo caracter (char).
� Compilada — significa que o código é verificado quanto à sintaxe,
passa por um processo de parsing, que verifica a estrutura gramatical
do código, para somente, então, ser compilado. Feito isso é gerado o
código assembler, no qual todas as instruções são traduzidas para o
código de máquina.
� Multiparadigma — é possível programar OO, ou utilizar a programação
funcional. Com essa linguagem é possível fazer programas embarcados
que trabalham diretamente com a comunicação com o hardware. Por
isso, dizemos que a linguagem C++ trabalha tanto com a programação
de alto como com a programação de baixo nível, sendo esta última, a
mais próxima do hardware.
� OO — esse é o seu grande diferencial em relação à linguagem C, pois
essa linguagem utiliza recursos como abstração, herança, encapsula-
mento e polimorfismo para construção do software.
A programação OO recomenda que um objeto tenha sua estrutura e seus métodos
tão privativos quanto for possível. Isso significa conhecer a especificação do método
sem ter os detalhes de como a execução realizada por ele é implementada.
Programação orientada a objetos: Java, C++ e C#6
Variáveis
Em C++ é possível declarar uma variável em qualquer momento do código,
dentro de uma instrução ou entre duas instruções.
Quanto à visibilidade, existem duas abordagens possíveis para uma variável:
local ou global.
� Variáveis locais: podem ser acessadas apenas dentro do bloco de ins-
truções no qual estão declaradas. Cada bloco compreende instruções
dentro de duas chaves {...}.
� Variáveis globais: podem ser acessadas em qualquer parte do código
ou arquivo. Para isso, basta que seja declarada onde se desejar. Quando
uma variável é global, dizem que está inserida no escopo do arquivo,
pois pode ser acessada em qualquer parte do todo.
Biblioteca stream
Para possibilitar a entrada (input) e a saída (output) de dados utilizando a
linguagem C++, é necessária a inclusão da biblioteca iostream.h, conforme
exemplo a seguir:
#include <iostream.h>
Para imprimir uma variável na tela, por exemplo podemos dizer da seguinte
forma:
#include <iostream.h>
int x = 20;
cout << "x é igual a " << x << endl;
A saída na sua tela será: x é igual a 20.
A linguagem C++ utiliza o cin para o comando de entrada de dados pelo
teclado e cout para a saída de dados na tela.
7Programação orientada a objetos: Java, C++ e C#
Constantes
É possível declarar uma constante dentro de um projeto C++. Você pode
tornar constantes: valores, ponteiros, conteúdo de um ponteiro e parâmetros
de uma função. Vale lembrar que, ao declarar um valor como constante não
é possível alterá-lo.
Exemplo: const float pi = 3,1415926.
Para montar seu ambiente de desenvolvimento, recomenda-se a utilização de integrated
development enviroment (IDE) — ou ambientes de desenvolvimento integrado, que
facilitam a rotina do projeto. Manusear arquivos grandes via prompt de comando ou
editor de textos não é uma tarefa aconselhável. Nesses casos, você pode contar com
algumas ferramentas que auxiliam nesse sentido. Uma delas é o CodeBlocks, cujo link
para instalação encontra-se a seguir. Um detalhe importante é que ao instalar a IDE
CodeBlocks, o compilador é instalado automaticamente. Para instalar no Linux, basta
escrever o seguinte comando no seu terminal:
$ sudo apt install codeblocks
https://bit.ly/2ejIyqR
Conhecendo a linguagem C#
Assim, como a linguagem C++, a LP C# é baseada na linguagem C, com
melhorias e características que unem a linguagem original com novos con-
ceitos e recursos. Trata-se de uma linguagem fortemente tipada, imperativa,
declarativa e OO.
A linguagem C# foi desenvolvida por Anders Hejlsberg e, atualmente,
pode ser encontrada na versão 8.0. É utilizada dentro do ambiente de desen-
volvimento .NET da Microsoft e tem muita aceitação no mercado, pois atende
diversas especificações para criação de softwares, como desenvolvimento Web,
mobile, metodologias ágeis como information technology infrastructure library
(ITIL) e até mesmo machine learning (aprendizado de máquina) que trata de
questões de mineração de dados em grandes bases, conhecidas como Big Data.
Programação orientada a objetos: Java, C++ e C#8
Deitel et al. (2007) explicam que C# é uma LP projetada para ser utilizada
na plataforma .NET e que, por ser baseada nas linguagens C, C++ e Java,
torna a migração dos desenvolvedores mais fácil, ao passo que seus recursos
se adaptam a cada uma das linguagens citadas e ainda acrescentam suas
capacidades próprias.
Essa plataforma é uma API feita para quem utiliza o sistema operacional
Windows. Já em sistemas operacionais Unix, é possível desenvolver por meio
do terminal ou de ferramentas como o Visual Studio Code e outras plataformas.
Sharp (2011) compara a adaptabilidade da LP C# a componentes quando
afirma que, enquanto a linguagem C desempenha importante papel no desen-
volvimento UNIX, devido a sua compatibilidade, a linguagem C# também é
compatível com diversos outros formatos, como eXtensible Makup Language
(XML) e o eXtensible Application Markup Language (XAML).
O Microsoft Visual Studio é um dos principais pacotes de programas de desenvolvi-
mento da plataforma .NET. Trata-se de um conjunto de ferramentas, utilizadas para o
desenvolvimento de aplicações móveis, para desktop, servidores Web e aplicações Web.
Você pode fazer o download dessa importante ferramenta para auxiliar na sua
experiência com o desenvolvimento utilizando C# no link a seguir.
https://qrgo.page.link/s8UrU
Plataforma ASP.NET
A plataforma ASP.NET foi criada pela Microsoft para solucionar problemas
de compilação e execução de aplicativos Web, além de fornecer ferramentas
que facilitassem o desenvolvimento de aplicações Web (SANTANA FILHO;
ZARA, 2002).
A plataforma ASP.NET permite também a criação de diversos tipos de
web services (serviços Web), que são aplicações que podem ser utilizadas na
internet. O usuário tem a sua disposição uma interface com métodos definidos,
na qual ele faz requisições a esses métodos a partir de protocolos da internet.
A Microsoft define web service como uma classe escrita em uma linguagem
9Programação orientada a objetos: Java, C++ e C#
suportada pela plataforma .NET, que é acessada via hypertext transfer protocol
(HTTP)(HADDAD, 2008).
Declaração de variáveis em C#
A declaração de variáveis nessa LP se assemelha à linguagem C e C++, con-
forme podemos ver no exemplo:
� Tipo + nome da variável = int MinhaVariável.
Deve-se sempre inicializar uma variável, atribuindo um valor inicial a
ela, assim:
� int MinhaVariável = 0;
As variáveis alocam determinadas quantidades de espaço na memória para
que seja possível armazenar os valores. O gerenciamento da memória nessa
linguagem é feito em duas áreas, como segue:
� stack — compreende um pequeno espaço de memória e funciona em
formato de pilha, o que em estrutura de dados significa que a inserção
e a remoção ocorrem em formato de pilha, o último elemento a entrar
é o primeiro a sair;
� heap — compreende uma área de memória bem grande e seu tamanho
muda de forma dinâmica, de acordo com o que está sendo utilizado.
Laços de repetição
No contexto da lógica de programação, laços de repetição são estruturas
de decisão que estão presentes em todas as linguagens de programação que
conhecemos. Possuem variações sintáticas, mas, de forma geral, fazem com
que um bloco de instruções se repita até que uma condição seja satisfeita.
Cada uma delas é utilizada conforme a necessidade dentro do código. Para
um melhor entendimento, você verá a seguir alguns tipos e em quais situações
podem ser utilizados.
Programação orientada a objetos: Java, C++ e C#10
Laço for
Nesta estrutura de repetição a lógica funciona da seguinte forma:
for (int i = 0; i <= 100; i++)
{
MessageBox.Show ("A variável alcançou o valor " +
i.ToString());
}
Esse bloco de repetição diz o seguinte:
� Para cada i (inteiro), enquanto a variável i for menor que 100, acrescente
1 até que i seja igual a 100. Quando o valor de i for 100, mostre na
tela a mensagem: “A variável alcançou o valor 100”.
Laço while
Essa estrutura basicamente diz que, enquanto a condição esperada não ocorrer,
o loop continuará a ser executado.
É muito comum ocorrerem erros de sintaxe durante a escrita do código que resultam no
chamado loop infinito, ou seja, a condição ficará sendo executado de modo contínuo
e não irá satisfazer a premissa determinada.
Laço do while
É semelhante ao laço while, porém, nessa estrutura, a condição é testada
no fim do laço. A diferença essencial entre os dois é o que se deseja fazer
dentro do código.
11Programação orientada a objetos: Java, C++ e C#
Laço for each
Sua principal função é varrer um array e todos os objetos que nele estão
contidos. O laço for each recebe em cada loop um elemento do array.
A Microsoft disponibiliza treinamento para todos os seus produtos, inclusive sobre a
plataforma .NET, bem como outros serviços, por exemplo a hospedagem de aplicações
Web por meio do Azure. Clique no link a seguir e confira.
https://qrgo.page.link/z6wbj
DEITEL, H. M. et al. C#: como programar. São Paulo: Pearson Education; Makron Books,
2007. 1153 p.
HADDAD, R. Web Services. Microsoft Docs, Redmond, 9 set. 2008. Disponível em: https://
docs.microsoft.com/pt-br/previous-versions/technical-articles/cc564893(v=msdn.10).
Acesso em: 28 ago. 2019.
HORSTMANN, C. Conceitos de computação com o essencial de C++. 3. ed. Porto Alegre:
Bookman, 2005. 712 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
SANTANA FILHO, O. V.; ZARA, P. M. Microsoft .net: uma visão geral para programadores.
São Paulo: Senac, 2002. 124 p.
SHARP, J. Microsoft Visual C# 2010. Porto Alegre: Bookman, 2011. 776 p. (Série Passo a Passo).
Leituras recomendadas
PERRY, J. S. Construções para aplicativos do mundo real: recursos de linguagem Java mais
avançados. IBM Developer, Armonk, 22 fev. 2016. Disponível em: https://www.ibm.com/
developerworks/br/java/tutorials/j-introtojava2/index.html. Acesso em: 28 ago. 2019.
PERRY, J. S. Fundamentos da Linguagem Java: programação orientada a objetos na pla-
taforma Java. IBM Developer, Armonk, 22 jan. 2016. Disponível em: https://www.ibm.com/
developerworks/br/java/tutorials/j-introtojava1/index.html. Acesso em: 28 ago. 2019.
Programação orientada a objetos: Java, C++ e C#12
DICA DO PROFESSOR
Mais do que conhecer as diversas linguagens de programação, bem como a orientação a objetos,
é importante entender que durante a vida profissional serão encontrados os mais diversos
programas e que eles precisam, de certa forma, comunicar-se entre si.
Neste sentido, o Web Service é importantíssimo, pois, por meio desse tipo de implementação, o
profissional de Tecnologia conseguirá permitir que todo o arranjo de sistemas que constituem
uma organização troque informações.
Na Dica do Professor, você poderá entender um pouco sobre Web Services, conceitos, padrões e
exemplos práticos.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
A orientação a objetos representa uma nova forma de pensar e desenvolver programas,
acrescentando economia e eficiência ao software.
Analise as informações:
1)
No que diz respeito às classes e aos objetos, as informações tratam, respectivamente, de:
A) Atributos e métodos da classe Conta.
B) Métodos e comportamentos.
C) Objetos e métodos da classe Conta.
D) Abstração da classe Conta.
E) Variáveis que podem ser declaradas na classe Conta.
O paradigma da orientação a objetos absorveu grande parte do mercado de
desenvolvimento e essa realidade cresce diariamente. Esse escopo tornou a forma de
programar mais produtiva, inserindo estrutura de dados, cada qual com a sua
utilidade, bem como fundamentos básicos que são os pilares da orientação a objetos.
Sabendo disso, analise a situação a seguir:
Dados os seguintes códigos Java:
2)
Código 1:
public class Pessoa{
public String nome;
public int idade;
}
Código 2:
public class Aluno extends Pessoa{
public String matricula;
}
Qual dos mecanismos da orientação a objetos está presente no código 2 em relação ao
código 1?
A) Abstração.
B) Herança.
C) Polimorfismo.
D) Encapsulamento.
E) Classe.
A linguagem Java é a mais utilizada mundialmente. Ela pertence à Oracle e tem
diversas bibliotecas e ambientes de desenvolvimento próprios para auxiliar o
desenvolvedor. Sua plataforma permite que se desenvolva aplicações em Java para
serem utilizadas em qualquer tipo de dispositivo. Como se chama o resultado da
compilação de um código Java resultante da execução de um programa nessa
3)
linguagem?
A) Compilador.
B) Interpretador.
C) Bytecode.
D) JVM (Java Virtual Machine).
E) IDE (Integrated Development Enviroment).
4) Juliano trabalha na empresa WTec e, recentemente, foi incumbido da tarefa de
desenvolver um sistema financeiro para um dos clientes da empresa. Passada a fase
da implementação, o próximo passo para Juliano foi demonstrar o sistema para o
cliente. Nessa ocasião, ele verificou que iria precisar realizar a integração com outros
sistemas. Qual solução Juliano poderá realizar para permitir que o seu sistema se
comunique com os demais?
A) Programação orientada a objetos.
B) Web Service.
C) SOAP (Simple Object Access Protocol).
D) XSD (XML Schema Definition).
E) XML (Extensible Markup Language).
Imagine o seguinte cenário: 5)
Pablo é desenvolvedor em uma empresa e precisa desenvolver um aplicativo para
uma pizzaria que permita que os pedidos sejam feitos por meio dele. Para cada sabor
de pizza, o sistema deve informar o respectivo valor.
Pablo realiza o projeto da seguinte forma:
Ele faz um teste inicial com apenas um sabor, para testar e definir o comportamento
da classe pizza:
public class PizzaCalabresa{
public void preparar () {
System.out.printIn("molho, queijo, calabresa");
}
public void assar () {
System.out.printIn("15 minutos");
}
public void cobrar (){
System.out.printIn("RS 12,00");
}
}
Em seguida, ele define no sistema como será a fabricação de uma pizza:
public classForno{
public void fabricar (PizzaCalabresa calabresa) {
calabresa.preparar ( );
calabresa.assar( );
calabresa.cobrar( );
}
Nesses dois blocos de código, Pablo define quais ingredientes compõem uma pizza de
calabresa e as três funções que poderão ser realizadas a partir da criação da classe
PizzaCalabresa.
Analise o segundo bloco de código e informe qual pilar da orientação a objetos (OOP)
representa o comportamento da classe Forno. Considere que Pablo deverá
implementar também as classes dos outros sabores de pizza.
A) Abstração.
B) Polimorfismo.
C) Herança.
D) Encapsulamento.
E) Estrutura de repetição.
NA PRÁTICA
Em sistemas, durante o projeto de um software, o profissional de TI precisa, dentre outras
coisas, conhecer o seu cliente, e procurar antever situações que possam causar indisponibilidade
de serviços ou vir a prejudicar a experiência do usuário de sua aplicação. Na linguagem Java é
comum tratar Exceptions, pois, caso o usuário insira comandos não esperados pela aplicação, os
blocos Try/Catch executarão um desvio evitando um erro ou quebra de execução do serviço por
falha.
Na Prática, você irá acompanhar a experiência da desenvolvedora Júnior da empresa Wtec e
como ela utilizou tal implementação durante a execução de um projeto de software.
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
ARM REHABILITATION: serious game para apoio à reabilitação utilizando interfaces
naturais
Atualmente, a tecnologia e o desenvolvimento não estão somente ligados ao entretenimento e às
situações de felicidade. O link a seguir demonstra o desenvolvimento de um jogo sério para
auxiliar pessoas que necessitam usar próteses a estimularem a prática. A ferramenta foi
desenvolvida utilizando a linguagem C#. Confira no link.
Conteúdo interativo disponível na plataforma de ensino!
GUJ: debates e discussões sobre programações
Você conhece o GUJ??? Este é uma das maiores comunidades virtuais quando o assunto é Java.
Lá, você encontra debates, discussões e suporte de conhecimento sobre a linguagem. Clique
para conferir.
Conteúdo interativo disponível na plataforma de ensino!
The RedMonk Programming Language Rankings
A empresa de análise de dados RedMonk mantém o mercado de desenvolvimento atualizado
sobre o ranking das linguagens de programação mais populares. Confira a colocação das
linguagens estudadas nesta Unidade de Aprendizagem.
Conteúdo interativo disponível na plataforma de ensino!
Programação funcional: cálculo lambda
APRESENTAÇÃO
Paradigma é um exemplo a ser seguido ou um ponto de vista da realidade. Em programação,
existem alguns paradigmas que determinam a base ou a forma de abordagem dos problemas e
suas respectivas soluções. Um dos paradigmas mais conhecidos é o da orientação a objetos que,
resumidamente, significa dividir um problema complexo em problemas menores e que permite,
com auxílio de conceitos próprios, desenvolver aplicações eficientes e versáteis.
Já o paradigma da programação funcional tem como base o cálculo lambda proposto por Church
na década de 1930, cuja premissa diz que os programas são construídos por meio da
implementação de funções matemáticas.
Nesta Unidade de Aprendizagem, você vai aprender conceitos de programação funcional e do
cálculo lambda, bem como verificar alguns exemplos de sintaxe desse cálculo na programação.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Explicar o que é programação funcional. •
Discutir o uso do cálculo lambda em programação funcional. •
Identificar a sintaxe do cálculo lambda. •
DESAFIO
Funções lambda são funções anônimas, ou seja, que não têm nome. Isso se dá em relação a
outros tipos, como no caso da linguagem Python, em que muito se usa o prefixo def para criar
uma função. Outro detalhe em uma função lambda é que ela não tem return, sendo
este implícito dentro da função e o retorno acontecendo sem a necessidade de escrita.
Assim, considere a seguinte situação:
Considerando tais informações, como você resolveria esse desafio utilizando funções lambda?
INFOGRÁFICO
Expressões lambdas são uma funcionalidade já disponível em muitas linguagens de
programação, e apresentam como uma de suas principais características a economia de linhas de
código para implementar a mesma instrução.
A versão 8 da linguagem Java já existe a implementação Lambda Expressions, que possibilita
inserir o paradigma funcional aos códigos Java, os quais trabalham sob o paradigma da
orientação a objetos.
A seguir, no Infográfico, veja de que forma ocorre a redução nas linhas de código para realizar o
mesmo bloco de instruções.
CONTEÚDO DO LIVRO
Programação funcional é o paradigma da programação que trata os problemas computacionais
de forma matemática por meio de funções. Ao contrário da programação imperativa, ele
determina que funções não podem ter estado ou ser mutáveis, ou seja, não devem causar efeitos
colaterais em outras partes do projeto.
Leia o capítulo Programação funcional: cálculo lambda, da obra Paradigmas de programação,
base teórica desta Unidade de Aprendizagem, e conheça esse paradigma funcional, saiba como
ele surgiu e também aprenda sobre o cálculo lambda que emprega essas características às
linguagens de programação.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Marcia Cristina Domingues Leite
Programação funcional:
cálculo lambda
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Explicar o que é programação funcional.
� Discutir o uso do cálculo lambda em programação funcional.
� Identificar a sintaxe do cálculo lambda.
Introdução
Em 1964, Gordon Moore já discorria sobre a diminuição contínua dos
componentes dos computadores e o aumento da sua capacidade de
processamento. Esses fatores são justificativas para a obsolescência dos
computadores em tempos cada vez mais curtos. Essa observação ficou
conhecida como Lei de Moore e marcou sua experiência na produção
dos primeiros circuitos integrados. Desde então, são desenvolvidos mi-
croprocessadores com cada vez mais núcleos de processamento.
Atualmente, existe um grande investimento em processadores com
mais de um núcleo, sendo cada núcleo correspondente a uma CPU.
Esse tipo de arquitetura se concentra no paralelismo dos seus chips e
impacta diretamente no mundo do desenvolvimento, que por muitos
anos foi baseado no processamento em sequência. Porém, tudo indica
que a Lei de Moore está prestes a se esgotar, pois os microprocessadores
estão chegando ao seu limite físico no que diz respeito à melhoria de
performance. Portanto, é necessário buscar alternativas para melhorar a
experiência do usuário na utilização do computador.
Neste capítulo, você conhecerá conceitos importantes sobre o escopo
da programação funcional, cálculo lambda e algumas sintaxes mostrando
essa implementação.
Avanço do paradigma funcional
As chamadas linguagens imperativas, com as quais se construíram programas
com sequência de instruções (fundamentados pela Máquina de Turing), estão
acompanhando as mudanças nos paradigmas do desenvolvimento, à medida
que o hardware se torna limitado no que se refere a melhorias de performance.
A necessidade de mudanças que incorporem rapidez ao software faz as
linguagens funcionais, que possuem em sua concepção conceitos matemáticos,
cada vez mais, ocuparem linhas de códigos nos projetos, sendo inseridas
efetivamente no mercado mundial do desenvolvimento.
Esse tipo de abordagem funcional traz benefícios para aplicações baseadas
em hardware e que possuem chips multinucleares, pois permite a execução
das instruções de forma paralela. O paradigma funcional se baseia no con-
ceito de função, ou seja, visa estruturar a construção de software seguindo o
modelo das funções matemáticas com base em princípios como imutabilidade
e ausência de estado. Isso serve para resoluçãode problemas complexos, que,
ao serem processadas pelo computador, serão simplificados até assumirem
uma forma normal.
Surgimento da primeira linguagem
Sebesta (2018) explica que a primeira linguagem de programação funcional
surgiu com a necessidade da resolução de problemas na área de inteligência
artificial, na década de 1950, quando matemáticos precisaram processar cál-
culos complexos a partir de listas encadeadas com símbolos matemáticos em
um computador.
Em 1959, surgiu a primeira linguagem funcional pura, até hoje conhe-
cida como list process language (LISP), criada pelo Dr. John McCarthy do
Massachussetts Institute of Technology (MIT). Inicialmente, essa linguagem
foi criada para manipular símbolos com o intuito de representar palavras e
símbolos inviáveis de serem representados pelas linguagens convencionais.
A necessidade disso era simular emoções e comportamentos humanos por
meio dessa simbologia.
Posteriormente à primeira versão da linguagem LISP, surgiram outras
derivações e, no ano de 1984, foi criada a linguagem Common Lisp, que
herdou conceitos de linguagens procedurais e considerada uma linguagem
de programação bem completa, embora muito criticada pelos cientistas que
buscavam uma linguagem pura, ou funcional.
Programação funcional: cálculo lambda2
Essa linguagem possui apenas dois tipos de estruturas de dados: átomos
e listas, em que átomos são os elementos matemáticos; e listas compreendem
os elementos ou parâmetros delimitados por parênteses.
Átomos
São dados primitivos da linguagem LISP e podem ser representados por dados
numéricos (inteiros, flutuantes, binário, hexadecimal) ou simbólicos (iniciam
com letra precedidos de qualquer caractere).
Listas
Representam uma sequência qualquer de átomos ou outras listas que possuem
delimitação por meio de parênteses. Esse tipo de lista difere dos arrays con-
vencionais pela forma de alocar espaço na memória, pois estruturam-se no
sentido de que seus elementos sejam tratados como a estrutura de uma pilha,
e as inclusões e exclusões são feitas no início da lista.
Atualmente, várias linguagens oferecem suporte para utilização de ex-
pressões lambda, entre elas, podemos mencionar Ruby, Python, C#, C++ e
JavaScript.
No paradigma funcional, as expressões representam de forma concreta a
informação, podem ser associadas a nomes e denotam valores determinados
pelo interpretador da linguagem. Devido ao seu alto nível de abstração, os
programas desenvolvidos com linguagens funcionais são mais claros, concisos
e eficientes.
Algumas linguagens funcionais são muito utilizadas para atividades que
se valem de suas características matemáticas, como os casos das linguagens
R (utilizada para desenvolver sistemas e processar dados estatísticos), Mathe-
matica (matemática simbólica) e K (para análise financeira).
Veja no link a seguir o que são e para que servem as linguagens de programação
funcional, além de dicas interessantes sobre esse paradigma de programação.
https://qrgo.page.link/d62AB
3Programação funcional: cálculo lambda
O Quadro 1 demonstra dados sobre empresas conhecidas mundialmente e
que utilizam em sua estrutura linguagens de programação funcional.
Fonte: Adaptado de Pointer (2018, documento on-line) e Costa (2017, documento on-line).
Linguagem Finalidade
ML Utilizada para verificação de hardware e
software na Intel e na Microsoft.
Scheme e LISP Utilizadas por diversas universidades
para o ensino da programação.
Scala Utilizada pelo Twitter para serviços de filas de mensagens.
Erlang Utilizada pelo Facebook no serviço de chat.
Haskell Utilizada como ferramenta para manipulação de programas
PHP. É uma linguagem puramente funcional e fortemente
tipada, uma das mais utilizadas nesse paradigma.
Quadro 1. Empresas que utilizam programação funcional
Na programação orientada a objetos, temos a transição de estados, na
qual variáveis e objetos assumem diferentes valores, fazendo o programa
realizar determinadas decisões no decorrer das variações e da execução. Na
programação funcional, isso não existe, em razão da premissa da ausência de
estado (stateless) e da imutabilidade (immutable).
Comportamento funcional
Veja as premissas de comportamento do paradigma funcional e como influen-
ciam no código do projeto a seguir.
� Funções: a programação funcional é toda baseada em funções que
dividem a estrutura do código em blocos semanticamente alinhados.
Uma função determinada pode receber outras funções como argumento
sem que isso afete externamente o escopo do projeto. Quando uma
função recebe outra função como argumento, recebe o nome de função
de alta ordem.
Programação funcional: cálculo lambda4
� Imutabilidade: a programação funcional lida basicamente com funções
e, à medida que uma variável é alocada na memória com um determinado
valor associado, esse valor permanece inalterado até o fim e em todas
as partes do código nas quais for usado.
� Tipo: existem linguagens de programação funcional fortemente tipadas,
ou seja, os possíveis erros são encontrados em tempo de compilação, o
que elimina a necessidade de verificação de tipo em tempo de execução.
Isso torna o programa mais rápido.
Na programação funcional não existem loops. Os laços devem ser criados por meio
de recursividade. As funções devem ser puras, ou seja, não podem depender de
nenhum elemento externo.
Cálculo lambda na programação funcional
Esse modelo foi projetado por Alonzo Church na década de 1930 e teve relevante
influência no desenvolvimento de linguagens que seguem este paradigma,
como as linguagens LISP e Haskell (MACHADO, 2013).
Sintaticamente, o cálculo lambda possui uma linguagem simples que repre-
senta problemas matemáticos por meio da combinação de funções e se baseia
na abstração. Como consequência, sua semântica se torna natural, permitindo a
fácil realização e solução de problemas computacionais. Rosser (1984) explica
que uma das principais características desse sistema é a definição de funções
que recebem um único parâmetro, permitindo seu reuso.
Uma expressão lambda consiste em uma função anônima que possibilita
passar uma função como argumento de outra função. Uma abstração lambda
é uma expressão que anuncia a seguinte função:
(ƛ x. + x1)
onde ƛ determina que existe uma função, ou seja, uma função de x que
incrementa x de 1.
5Programação funcional: cálculo lambda
Expressões lambdas são funções lambdas que não pertencem a nenhuma
classe. Esse tipo de expressão é comumente utilizado para percorrer, filtrar e
extrair dados de coleções de forma simples e direta. A Figura 1 demonstra o
que significa cada parte da expressão lambda.
Figura 1. Sintaxe lambda.
O operador lambda representado pela seta ( ->) divide a expressão da
seguinte forma: tudo o que está antes do operador especifica os parâmetros de
entrada, caso existam; do lado direito está a ação que deve ser desempenhada.
No cálculo lambda:
� todas as funções são anônimas;
� é possível gerar operadores mais complexos a partir da combinação de
operadores e funções básicas;
� pode ser tipado ou não;
� todas as funções são chamadas de alto nível, pois podem ser usadas
como argumento e retornadas em outras funções.
Programação funcional: cálculo lambda6
Um programa lambda se escreve com a implementação de um conjunto
de expressões lambda. O cálculo lambda é realizado por meio dos seguintes
operadores:
� aritméticos — +, –, * e /;
� operadores lógicos, onde:
■ AND = λx. λy . x y x;
■ NOT = λx . λa. λb. x b a;
■ OR = λx . λy. x x y;
■ IFTHENELSE = λx. λa. λb. x a b;
� constantes lógicas — true, false.
Abstrações lambda
Um termo lambda pode ser uma variável x, assim como um termo t. No entanto,
uma vez que o termo lambda é precedido de outra variável, diz-se que houve
uma abstração lambda, conforme exemplo a seguir:
ƛx.t
Onde: a função anônima recebe x e retorna t, pois a abstração da variável
x a liga ao termo t.
Recursividade
Como visto anteriormente, a programação funcionalnão possui loops e,
para que seja possível a chamada das funções, uma de suas características é
a recursão, definida pela capacidade da função de chamar a si mesma várias
vezes, até que uma condição seja satisfeita. O exemplo a seguir demonstra o
cálculo do fatorial utilizando a linguagem de programação Python:
lambda _ fatorial = lambda i:1 if i==0 else i*lambda _ fatorial(i-1)
print(lambda _ fatorial(4))
# 4 * 3 * 2 * 1 = 12 * 2 = 24
7Programação funcional: cálculo lambda
Hartel et al. (2001) pontuam três vantagens da programação funcional:
� nível é mais alto em relação às linguagens tradicionais;
� mais próximas da especificação;
� as variáveis não mudam de valor durante a execução, ou seja, não há efeitos co-
laterais na avaliação.
Sintaxe do cálculo lambda
Em uma expressão lambda, assim como na programação imperativa, o uso de
funções se assemelha. Nela, também encontramos uma lista de parâmetros e um
bloco de instruções. Quando a expressão lambda é simples, não é necessário
o uso de chaves, por exemplo,
( ) -> x+y
Semelhante ao método da programação imperativa, as expressões lambda
diferem pelo fato de não possuírem nome, ou seja, não é necessário declarar
o tipo de retorno ou cláusulas para tratamento de exceções.
A linguagem lambda oferece variáveis, abstração e aplicação de termos,
conforme apresentado a seguir.
Dados
Tratam de valores booleanos, operações lógicas e aritméticas e coleções
(pares e listas). Por exemplo, booleanos em lambda podem ser representados
da seguinte forma:
True = ƛx x.y
False = ƛx y.y
Nessa lógica, existe uma escolha: as funções têm dois parâmetros e retornam
um. O True escolhe o primeiro e retornar; e o False escolhe o segundo.
Programação funcional: cálculo lambda8
Para realizar uma negação, utilizamos a função NOT que recebe um boo-
leano e retorna a sua aplicação nos parâmetros False e True.
const not = b => b (F, T)
return (not(t
Estruturas de controle
Compreendem estruturas condicionais, definições locais e recursividade,
veja o exemplo:
if = ƛx.(ƛa.(ƛb.x a b))
const If = condition => then => else => condition (then) (else)
Nesse caso, se a condição for verdadeira, o primeiro parâmetro é retornado,
caso contrário, ela retorna o segundo parâmetro.
Funções de primeira classe (first class function)
Quando é possível tratarmos funções como valores, passando ela como um
argumento de outras funções ou até mesmo retornar como resultado de outras
funções, temos as funções de primeira classe. No exemplo a seguir, a função
anônima, lambda, foi armazenada em uma variável:
func = lambda x: x
def func _ 2(x):
return x + 2
A variável que armazena a função foi inserida em uma estrutura, assim
como uma função gerada com def
lista = [func, func _ 2]
lista _ 2 = [lambda x: x, lambda x: x+1]
Nesse caso, as funções foram definidas dentro de uma estrutura.
9Programação funcional: cálculo lambda
Funções puras
Na programação funcional se trabalha com funções e variáveis, e não há objetos
e métodos. Esse tipo de programação é conhecida como stateless (as funções
podem ser chamadas em diversas partes do código, mas a cada chamada
será como se fosse a primeira, ou seja, ela não tem estado) e immutable (uma
vez que um valor é atribuído a uma variável, ele permanece durante toda a
execução do programa).
Outra característica importante da programação funcional são as funções de
alta ordem, que significa passar uma função como parâmetro de outra função.
Assim, a função se torna um parâmetro dentro da sua função.
Por isso, é comum dizer que, para que uma função seja considerada uma
função pura, ela não pode ter efeito colateral, ou seja, não pode alterar o estado
de qualquer variável ou objeto que possa ser observado fora do escopo da
função. Outra premissa importante sobre as funções puras é que elas devem
depender apenas de seus argumentos.
Veja um exemplo de uma função impura e como ela pode se tornar pura
por meio da programação funcional.
Função impura:
salva _ usuario (usuario) = {
http (“POST”, “ /usuario”, usuario)
}
Função pura:
salva _ usuario (usuario) = {
method: “POST”,
path: “/usuario”,
data: usuario
}
A grande diferença da função impura é caracterizar uma linguagem impe-
rativa, na qual inserimos o passo a passo das instruções. No segundo exemplo,
retornamos declarativamente o que deve ser feito, fazendo com que cada vez
em que a função for chamada, apenas um usuário seja inserido.
Programação funcional: cálculo lambda10
Funções de ordem superior
São funções que permitem receber ou retornar outras funções como resposta,
conforme detalhado a seguir.
Map
Como o seu nome já sugere, ela mapeia uma lista em uma função e retorna
seus resultados. Vamos utilizar um exemplo em Python:
lista = range(1, 6)
nova _ lista = map(lambda x:x*2, lista)
for i in nova _ lista:
print i
Essa função solicita a varredura da lista e a multiplicação de todos os
resultados por 2. A saída é a seguinte:
2
4
6
8
10
Filter
Semelhante a Map, retorna uma lista, mas apenas os elementos que, ao pas-
sarem pela função forem verificados, vão para a lista se forem verdadeiros.
No exemplo a seguir, a função pede para que os elementos da lista sejam
divididos por dois e, apenas aqueles cujo resultado da divisão por dois seja
zero, inseridos na lista.
lista1 = range(1, 20)
lista2 = filter (lambda x: x % 2 == 0, lista1)
for i in lista2:
print i
11Programação funcional: cálculo lambda
A saída é a seguinte:
2
4
6
8
10
12
14
16
18
Reduce
Utiliza dois argumentos de forma cumulativa que são inseridos em uma nova
lista. Imagine uma lista com cinco elementos que passa por uma função
Reduce que diz que, a cada passagem pela função, dois itens devem ser
somados. Dessa forma, temos a seguinte sintaxe:
listaA = range(1, 5)
listaB = reduce (lambda x,y: x+y, listaA)
for i in listaB:
print i
A saída de tela seria a seguinte:
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15
Funções anônimas
São funções que podem ser declaradas em qualquer contexto e não precisam,
necessariamente, ter um nome.
Programação funcional: cálculo lambda12
C Não
PASCAL Não
C++ Sim (a partir da versão 11)
Java Script Sim
Python Sim
Ruby Sim
C# Sim (a partir da versão 3.0)
Java Sim (a partir da versão 8)
Quadro 2. Linguagens que fornecem suporte para o uso de expressões lambda
COSTA, G. S. O que as empresas usam? Toca do Tux, [S. l.], 6 out. 2017. Disponível em:
http://www.tocadotux.com.br/2017/10/o-que-as-empresas-usam.html. Acesso em:
1 set. 2019.
HARTEL, P. H. et al. Declarative languages in education. In: Encyclopaedia of micro-
computers. New York: Marcel Dekker, 2001. p. 79–102. Disponível em: https://research.
utwente.nl/en/publications/declarative-languages-in-education. Acesso em: 1 set. 2019.
MACHADO, R. An introduction to lambda calculus and functional programming. In:
WORKSHOP-SCHOOL ON THEORETICAL COMPUTER SCIENCE (WEIT), 2., 2013, Rio Grande.
Proceedings [...]. Rio Grande: Centro de Convenções do CIDEC-SUL/FURG (Centro Inte-
grado de Desenvolvimento do Ecossistema Costeiro do Extremo Sul), 2013. p. 26–33.
POINTER, I. Conheça as 5 melhores linguagens de programação para inteligência
artificial. ComputerWorld from IDG, São Paulo, 4 jul. 2018. Disponível em: https://com-
puterworld.com.br/2018/07/04/conheca-5-melhores-linguagens-de-programacao-
-para-inteligencia-artificial/. Acesso em: 1 set. 2019.
ROSSER, J. B. Highlights of the History of the Lambda-Calculus. Annals of the History of
Computing, Piscataway, v. 6, n. 4, p. 337–349, Oct./Dec. 1984.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
13Programação funcional: cálculo lambda
Leituras recomendadas
BARENDREGT, H.; BARENDSEN, E. Introduction to lambda calculus. Nijmegen: Catholic
University of Nijmegen, 2000. 53 p. Disponível em: http://www.cse.chalmers.se/research/
group/logic/TypesSS05/Extra/geuvers.pdf. Acesso em: 1 set. 2019.
COOPER,S. B.; VAN LEEUWEN, J. Alan Turing: his work and impact. Amsterdam: Elsevier,
2013. 944 p.
MENDES, F. J. Consertando falta de espaço no cálculo lambda. Webschool-io, [S. l.],
14 ago. 2018. Disponível em: https://github.com/Webschool-io/matematica-para-
-programadores/tree/master/calculo-lambda. Acesso em: 1 set. 2019.
TUCKER, A. B. Linguagens de programação: princípios e paradigmas. 2. ed. Porto Alegre:
AMGH, 2009. 630 p.
Programação funcional: cálculo lambda14
DICA DO PROFESSOR
Enquanto o paradigma imperativo emprega instruções sobre o funcionamento do computador, o
paradigma funcional traduz essas instruções para funções matemáticas.
Na programação funcional existem algumas particularidades, como imutabilidade e ausência de
estados, que a diferem da imperativa, fazendo com que sua clareza dentro do escopo do código
se torne muito definida.
A seguir, na Dica do Professor, veja um comparativo entre a linguagem imperativa (orientada a
objetos) e a linguagem funcional (baseada em funções matemáticas).
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) Funções lambda, além de anônimas, reduzem expressões de forma significativa,
fazendo com que o maior número de instruções possa ser expresso na mesma linha.
Apesar de não ser considerada uma linguagem funcional, o Python vem
implementando diversas funcionalidades, entre elas as funções lambda, de modo a
permitir a otimização de seu código.
Dada a seguinte função lambda na linguagem Python:
lista = [2,3,5,7]
nova_lista = map(lambda x:x*2, lista)
for i in nova_lista:
print i
O que deve ser mostrado na tela?
1 A)
1,5
2,5
3,5
B) 4
6
10
14
C) 0
1
3
5
D) 2
3
5
7
E) 2
3
3
7
2) As funções internas ou embutidas, como filter, permitem que os dados sejam filtrados
de uma lista a partir de uma instrução computacional. Essa função evita a
necessidade de mudança de estado das variáveis, que tende a tornar expressões
impuras.
Observe a função e diga qual mecanismo lambda está expresso na sentença:
lista1 = range(1, 20)
lista2 = filter (lambda x: x % 4 == 0, lista1)
for i in lista2:
print i
A saída é a seguinte:
4
8
12
16
A) Filter.
B) Map.
C) Reduce.
D) Zip.
E) Recursividade.
As funções Map, Filter e outras nos permitem manipular listas de forma limpa e 3)
prática, sem que isso cause efeitos colaterais no restante do código. Sabendo disso,
analise a seguinte situação:
Laura está modificando o sistema financeiro da universidade em que trabalha. O
gerente financeiro solicitou que fossem calculados diariamente os valores recebidos
nas negociações com os alunos. Laura sabe que todos os valores inseridos no sistema
são armazenados em um array. Qual função lambda Laura poderá utilizar para
somar todos os valores inseridos no sistema e, ao final do dia, entregar para seu
gerente o montante total?
A) Map.
B) Filter.
C) Booleana.
D) Reduce.
E) Soma.
De modo geral, o uso de funções lambda entrega ao desenvolvedor a possibilidade de
um código mais limpo, conciso e imutável. São as chamadas funções puras. Para
tanto, é preciso compreender a notação nativa da linguagem e a notação lambda,
para só então entender a transformação realizada nas linhas do código. Sabendo
disso, analise a situação:
Dada a função soma em Python, escolha a alternativa que representa a conversão
utilizando lambda para reescrever o código:
def soma (a,b,c):
return a+b+c
>>> x = soma
4)
>>> x(10,20,30)
>>>60
A) f = (lambda a+b+c : a,b,c)
f (10,20,30)
B) f = (lambda a,b,c : a+b+c)
return (10,20,30)
C) f = (lambda a,b,c : a+b+c)
f (10,20,30)
D) f (lambda) = ( a,b,c : a+b+c)
f (10,20,30)
E) f (lambda) = (a,b,c : a+b+c)
return (10,20,30)
De forma muito clara e amigável, a função Filter realiza a verificação de uma lista e a
extração dos elementos solicitados pela expressão ou função diretamente ligada a ela.
Como resultado, ela traz uma nova lista contendo os elementos extraídos após a
execução da função.
Analise a função lambda que recebe um array com as alturas de todos os candidatos
de uma agência de propaganda. Verifique a sintaxe e marque a alternativa que
informa o que a função irá retornar na tela:
alturaMetros=[1.65,1.80,1.72,1.74,1.68,1.91]
def main( ):
5)
print filter(lambda x: x > 1.70 > 1.90 ,alturaMetros)
return 0
if name == ' main ':
main( )
A) [1.80, 1.72, 1.74, 1.91]
B) [1.65, 1.80, 1.72, 1.74]
C) [1.80, 1.72, 1.74, 1.91]
D) [1.80, 1.72, 1.74, 1.68, 1.91]
E) [1.80, 1.72, 1.74]
NA PRÁTICA
Um dos grandes objetivos da programação funcional é aumentar a performance das aplicações a
nível de software, já que, conforme a Lei de Moore, a capacidade de aumento da performance
dos processadores está chegando no seu limite no que diz respeito ao hardware.
A seguir, no Na Prática, acompanhe como Maurício, desenvolvedor de uma empresa de
softwares, está testando a programação funcional para inserir na sua prática diária.
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Expressões lambda (guia de programação em C#)
Você quer aprender a implementar expressões lambda em C#? Confira a página a seguir, com
vários detalhes e dicas.
Conteúdo interativo disponível na plataforma de ensino!
Java 8: expressões lambda
A seguir, veja uma série de vídeos que auxiliam a implementar códigos Java utilizando
expressões lambda.
Conteúdo interativo disponível na plataforma de ensino!
MC 346: paradigmas da programação Lisp
O estudo a seguir traduz, passo a passo e de forma clara, as principais funcionalidades desta
linguagem do paradigma funcional que utiliza expressões lambdas no seu escopo.
Conteúdo interativo disponível na plataforma de ensino!
Um catálogo de refatorações envolvendo expressões lambda em Java
Neste estudo, você verá o uso do cálculo lambda no processo de refatoração para a melhoria e
otimização de um código no âmbito do desenvolvimento. Por meio da refatoração, foi possível
identificar as novas funcionalidades da linguagem Java 8, agora sob o paradigma funcional.
Conteúdo interativo disponível na plataforma de ensino!
Uma linguagem de programação quântica orientada a objetos baseada no Featherweight
Java.
Para saber mais sobre o tema, leia o estudo a seguir que apresenta a utilização de uma
linguagem de programação que, embora orientada a objetos, utiliza conceitos de programação
funcional baseados na linguagem Haskell, cuja estrutura é puramente funcional.
Conteúdo interativo disponível na plataforma de ensino!
Programação funcional: funções puras
APRESENTAÇÃO
Vivencia-se um período de transição no que se refere a modelos computacionais e paradigmas
de programação. As linguagens imperativas, subsidiadas por arquiteturas concorrentes, baseadas
no modelo de Von Neumann, estão cedendo espaço para o paralelismo computacional, em um
primeiro momento trazido pelos processadores multinucleares. O segundo momento é o
crescimento do paradigma funcional no desenvolvimento, trazendo conceitos matemáticos e
uma forma mais pura para a resolução de problemas em sistemas.
O modelo de Alonzo Church denota a utilização de funções matemáticas para a resolução de
problemas, adotando conceitos totalmente contrários, como imutabilidade, ausência de estados e
funções de alta ordem.
Nesta Unidade de Aprendizagem, você irá entender a programação funcional, o conceito de
funções puras e a análise de sua aplicação.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Explicar os principais conceitos da programação funcional.•
Determinar o uso de funções puras em programação funcional. •
Analisar a implementação de uma função pura. •
DESAFIO
A programação funcional utiliza funções matemáticas para buscar lógicas e soluções para
sistemas. Ela agrega valor ao código à medida que requer menos linhas de códigopara resolver
o mesmo problema que impõe a necessidade de várias linhas para outros tipos de paradigma.
Embora esse paradigma requeira estudo aprofundado por parte do desenvolvedor, noções
iniciais auxiliam a entender de que forma acontece a programação funcional em uma aplicação.
Imagine que você trabalha como desenvolvedor de uma Universidade e recebeu uma solicitação
da colega da biblioteca. Ela precisa que você implemente no sistema uma forma de melhor
localizar os livros.
De que forma você implementaria uma solução em Python, com base nos conceitos de
programação funcional vistos nesta Unidade de Aprendizagem?
Considere a linguagem de sua preferência e tome como exemplo as seguintes informações:
Lista 1: ['1: Literatura', '2: Administração', '3: Redes de computadores']
Lista 2: ['Machado de Assis', 'Philip Kotler', 'Andrew Tanembaum']
INFOGRÁFICO
A programação funcional vem chamando a atenção dos desenvolvedores nos últimos anos,
devido a sua arquitetura voltada para o paralelismo computacional. Na hora de escolher uma
linguagem para seu projeto, é importante saber a diferença entre programação funcional e
programação orientada a objetos, em que conceitos mais conhecidos cedem espaço a novos
conceitos e novas possibilidades de resolução de problemas computacionais, bem como cada
linguagem e seus respectivos paradigmas.
No Infográfico a seguir, você verá um comparativo entre essas duas importantes escolhas: o
paradigma funcional e o paradigma orientado a objetos.
CONTEÚDO DO LIVRO
A programação funcional traz em seu escopo premissas propostas por seu criador, Alonzo
Church, na década de 1930. Nesse sentido, ele defendia a utilização de expressões matemáticas
para a resolução de problemas complexos e que, de fato, foram utilizados em projetos
envolvendo Inteligência Artificial.
De lá para cá, o cálculo Lambda tem sido utilizado em diversas linguagens de programação, até
mesmo naquelas que não são consideradas funcionais. Isso denota sua importância e
contribuição nas questões lógicas das aplicações que estão sendo desenvolvidas. Além de elevar
o nível de abstração do código, conceitos de pureza, imutabilidade e ausência de estado
entregam linhas concisas e claras aos códigos das mais variadas aplicações.
No capítulo Programação funcional: funções puras, da obra Paradigmas de programação, você
verá conceitos importantes da programação funcional, bem como funções de ordem superior e
alguns exemplos práticos de sua implementação em diversas linguagens.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Marcia Cristina Domingues Leite
Programação funcional:
funções puras
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Explicar os principais conceitos sobre a programação funcional.
� Determinar o uso de funções puras em programação funcional.
� Analisar a implementação de uma função pura.
Introdução
A programação funcional tem origem na necessidade de implementações
em inteligência artificial (IA), aprendizado de máquina (machine learning)
e ciência cognitiva. Essa forma de programar trata os problemas sob o
ponto de vista matemático, evitando questões como estados e mutação
de dados (TUCKER; NOONAN, 2009).
Um código funcional é definido, basicamente, por não causar im-
pactos em outras partes do código que não seja dentro do escopo de
uma função. Essa função retornará sempre o mesmo resultado, indepen-
dentemente do número de vezes que for chamada durante a execução.
A programação funcional institui um alto nível de abstração no código,
possibilitando uma maior produtividade e programas mais concisos
e fáceis de entender. Outra vantagem é o tratamento e a verificação
de erros, pois, por se tratar de programas que não possuem estados
ou mutabilidade de dados, é mais simples testar as partes do código e
identificar possíveis erros.
Neste capítulo, você verá conceitos do paradigma funcional, carac-
terísticas e comportamento, entre os quais o conceito de funções puras
e como elas se aplicam na implementação de um código.
Paradigma funcional: principais conceitos
As linguagens de programação funcional surgiram a partir de conceitos ba-
seados em funções matemáticas e no cálculo lambda, proposto por Alonzo
Church na década de 1930.
A abordagem declarativa diverge do modelo mais utilizado, o imperativo,
e está, gradativamente, sendo inserida no mercado, tendo participação nas
linhas de código de empresas como Facebook e Twitter.
Tucker e Noonan (2009) explica que, como não há uma ideia de estado no
escopo funcional, é impossível incrementar ou decrementar considerando a
inexistência de estados e de variáveis, o que implica a inexistência de laços,
que são substituídos por repetições de uma função.
A programação funcional é baseada em alguns princípios que a funda-
mentam como linguagem declarativa, conforme você verá nos itens a seguir.
Funções puras
São aquelas que não produzem efeitos colaterais dentro do escopo do projeto,
pois não apresentam estados internamente, daí o conceito stateless (sem estado).
Isso significa que, de acordo com o parâmetro de entrada, existirá sempre a
mesma saída. Portanto, ela não pode depender de nenhum estado mutável e
não pode influenciar acessando ou alterando variáveis globais.
Transparência referencial
Diz-se que uma função possui transparência referencial quando seu valor
depende apenas dos valores de seus argumentos, ou seja, a função sempre
produz o mesmo resultado a partir dos mesmos parâmetros.
Imutabilidade
Trata-se de um aspecto do pensamento funcional. Uma vez que um determinado
valor é atribuído a uma função, ele permanecerá imutável até o fim. Conside-
rando a existência um bug complexo no sistema, por meio da imutabilidade
é muito mais simples realizar testes, visto que não é necessário realizar toda
a sequência de variações de estado de um dado atribuído.
A imutabilidade tende a consumir mais memória, pois se trabalha
com cópias e não com referências, entretanto ela permite o paralelismo
computacional.
Programação funcional: funções puras2
Expressões lambda
São funções anônimas que especificam os parâmetros e a definição de uma
função. Church (1936) definiu o cálculo lambda puro, da seguinte forma
(TUCKER; NOONAN, 2009, p. 363):
� qualquer identificador é uma expressão lambda;
� se M e N forem expressões lambda, então a aplicação de M a N escrito
como (M, N) é uma expressão lambda;
� abstrações como x.M também são expressões lambda.
O cálculo lambda é uma linguagem intermediária que permite implementar
de forma mais eficaz as funções matemáticas a nível de linguagem de máquina.
Por meio de funções como Map, Filter, Reduce, Zip e outras, realizamos
operações de soma, separação e mapeamento em expressões lambda. Esse
paradigma instituiu a inserção de listas em linguagens imperativas como
Python e C#. Com essa estrutura de dados é possível utilizar operadores para
realizar cálculos e formar expressões.
Recursão
Quando se tem um grande problema, é importante encontrar a forma mais
eficaz de resolvê-lo. A recursão permite a divisão de um grande problema em
partes menores. Dessa forma, ela permite que uma função chame a si mesma
reiteradas vezes, até que o problema seja sanado. É um recurso importante
dentro do contexto da programação funcional, em que não é possível incre-
mentar ou decrementar valores devido à inexistência de variáveis e estados.
Funções de primeira classe (first-class functions)
Uma função possui funções de primeira classe quando trata suas funções
como se fossem valores:
� atribuindo a variáveis;
� aceitando como argumentos de outras funções;
� permitindo retornar funções como resultados de outras funções.
3Programação funcional: funções puras
Vejo o exemplo em Python a seguir:
>>> objetos = ["relógio","casa", "mala"]
>>> sorted (objetos)
>>> ["casa", "mala", "relógio"]
>>>meu _ sorteio = sort
>>>meu _ sorteio (objetos)
>>> ["casa", "mala","relógio"]
>>> sorted == meu _ sorteio
>>> True
Nesse exemplo, foi implementada a função que organiza os objetos de
forma alfabética, em seguida a função objetos é passada como parâmetro para
outra função, o que denota uma função de primeira-classe.
Funções de primeira-ordem
São funções que permitem receber ou retornar outras funções.
Currying
É uma técnica que permite passar argumentos de forma parcial para uma fun-
ção. Caso uma função necessite de quatro argumentos para ser executada e você
passar apenas dois, o resultado será uma função que aceita dois argumentos.
Esse processo se repete até que todos os argumentos tenham sido passados.
Compose (function composition)
É uma técnica que permite criar uma função a partir da combinação de outras
funções. Em outras palavras, o resultado de uma função é passado como
argumento para uma próxima função, até que todas as funções tenham sido
executadas. Por exemplo:
Função.argumento -> func3(func2(func1(argumento)))
Programação funcional: funções puras4
O fato de não possuir classes e métodos impõe ao desenvolvedor dúvidas
na hora de optar pela linguagem de programação funcional. Contudo, é preciso
entender que esse tipo de paradigma, fortemente tipado, oferece estruturas, por
exemplo nas linguagens Erlang e Elixir, e tipagem, como é o caso da tradicional
Haskell. A linguagem Haskell adota a teoria das categorias, na qual seus tipos
se encaixam matematicamente por meio de suas funções.
Funções puras na programação funcional
Estamos acostumados ao paradigma da orientação a objetos (OO), em que
temos diversos métodos retornando diferentes resultados a partir dos mesmos
parâmetros, o que caracteriza a impureza na programação.
As linguagens de programação funcional, de modo geral, classificam-se
de duas formas: linguagens funcionais puras e linguagens funcionais impuras.
As linguagens puras têm como principal característica suas funções serem
executadas dentro de seu próprio escopo e não produzirem efeitos em outras
partes do código, ou seja, possuírem ausência de estados anteriores. Basica-
mente, quando utilizamos um determinado parâmetro de entrada, sempre
teremos o mesmo resultado na saída. Isso permite que não seja necessário
realizar o controle da ordem das execuções.
Outra característica importante das funções puras é a chamada transpa-
rência referencial, que como o próprio nome diz, permite referenciarmos o
resultado de uma função em vez de toda sua expressão, o que se deve justamente
ao fato dela produzir sempre o mesmo resultado.
Uma função pura sempre terá o mesmo retorno para a mesma entrada. É muito mais
fácil criar funções com efeitos colaterais, por isso deve-se estar atento.
5Programação funcional: funções puras
High-order functions (funções de ordem superior)
Como visto anteriormente, essas funções recebem outras funções como ar-
gumento e/ou retornam funções como resposta. Existem algumas funções de
ordem superior que fazem o código ser puro, ou seja, não sofrer nem gerar
influência fora do escopo da função. As mais conhecidas são abordadas a seguir.
Função map
Esta função permite ao desenvolvedor executar ou varrer uma lista de tamanho
N, além de executar a instrução necessária até que a condição seja satisfeita.
Em outras palavras, essa função permite que um array seja varrido e que
cada elemento passe pela instrução desejada. Isso gerará uma nova lista com
os resultados da execução de cada elemento da lista inicial.
O exemplo da Figura 1, proposto por Tucker e Noonan (2009) na linguagem
Haskell, utiliza a função maphead, que equivale a função map e demonstra
sintaticamente como se aplica essa função.
Figura 1. Exemplo função maphead em Haskell.
Fonte: Adaptada de Tucker e Noonan (2009).
Função filter
Assim como na OO, quem programa utilizando o paradigma funcional, em
dadas situações, precisará selecionar determinados itens de uma coleção para
realização de testes ou outra finalidade qualquer. Nesse caso, a função filter é
que realiza essa separação, utilizando o critério declarado pelo programador
(DU BOIS, 2008). Du Bois utiliza um exemplo muito simples para exemplificar
como funciona essa função em Haskell:
Haskell > filter par [2, 4, 5, 6, 10, 11]
[2, 4, 6, 10]
Programação funcional: funções puras6
O exemplo apresentado demonstra uma função Haskell que solicita que os
elementos pares da lista sejam filtrados. Dessa forma, a instrução é executada
e gera uma nova lista (array), com os dados filtrados pela função.
Função reduce
É uma função que realiza a combinação de dois parâmetros de entrada, com-
binando o valor acumulado até o momento com o próximo elemento da lista.
Como o próprio nome diz, a ideia é reduzir a informação de um array para um
só número. Utilizando essa função, é simples realizar, por exemplo, o cálculo
de todos os elementos de uma lista. Ela aplica de forma cumulativa a instrução
da função até que se encontre um único valor. Por exemplo:
>>> reduce (lambda x: x*x, [1,2,3])
>>>6
Ou, ainda,
>>> reduce (lambda x,y, x+y, [1,2,3}
>>>6
Os dois exemplos mostram operações nas expressões lambda em que é
solicitada a multiplicação e, posteriormente, a soma dos argumentos x e y
até que se chegue a um único dígito.
Função zip
Essa função, também utilizada por outras linguagens que usam o paradigma
funcional, retorna uma lista de tuplas, na qual, em cada tupla, são intercalados
os valores de cada lista. Veja o exemplo:
>>> lista1 = ['laranja', 'banana', 'pêssego']
>>> lista2 = ['1', '2', '3']
>>>func _ zip (zip(lista1,lista2))
>>>[('laranja', '1'), ('banana', '2'), ('pêssego', '3')]
7Programação funcional: funções puras
Paralelismo significa a utilização de processamentos independentes e paralelos sem
que se comuniquem ou interfiram um no outro. O resultado sempre será o mesmo,
independentemente da ordem em que as operações forem executadas no processador;
isso permite que esse modelo de processamento seja considerado mais rápido em
comparação ao processamento por concorrência (MARLOW, 2009).
Códigos limpos com funções puras
Vários conceitos são discutidos no paradigma funcional, que se baseia em
funções matemáticas para resolução de problemas. Alonzo Church acreditava
que funções com estados mutáveis causavam problemas, e que o conceito de
funções puras deveria ser adotado na prática funcional.
Funções puras não causam efeitos colaterais, gerando sempre o mesmo
resultado a partir da mesma entrada, e sua execução não gera efeitos fora do
escopo da própria função.
Vale destacar que, exceto códigos para fins de análise estatística, é inviável
produzir códigos totalmente puros, considerando que a mudança de estado
é necessária para a comunicação externa de funções e para o código como
um todo. A ideia é criar o maior número de partes de código funcional para
melhorar a performance da aplicação.
Considere o seguinte exemplo na linguagem Python:
>>> func _ pura = lambda x: x+1
>>> func _ pura (300)
301
Essa função lambda denota uma função pura, pois a saída dos dados será
a mesma a partir da mesma entrada, ou seja, todo número que for inserido
na função somará 1 e será executado apenas dentro do escopo dessa função.
Programação funcional: funções puras8
As linguagens Haskell e Scheme serviram de base para outras linguagens
somarem as suas bibliotecas instruções funcionais, por exemplo a linguagem
Python, que está sendo utilizada em exemplos neste capítulo. Contudo, é
preciso lembrar que Python não é uma linguagem totalmente funcional, o
que ocorre é que algumas operações funcionais podem ser implementadas
em Python, como visto.
Vantagens
Caso você fique em dúvida sobre a implementação de funções puras, seguem
algumas vantagens desse tipo de implementação no seu código:
� são fáceis de testar e depurar, pois não criam dependências em outras
partes do código;
� seu valor de retorno pode ser armazenado devido à questão da
imutabilidade;
� possuem transparência referencial, ou seja, umaexpressão pode ser
substituída pelo seu resultado sem que isso gere impacto nele. Isso
facilita para o compilador e permite a criação de outras funções utili-
zando a primeira como parâmetro, sem correr riscos de mudanças de
estado no meio do caminho.
O Quadro 1, adaptado de uma palestra de Ananja Vakil, ilustra a realidade
sobre a ideia e a pretensão da notação lambda e como isso funciona no universo
do desenvolvimento. O cálculo lambda de Church inviabiliza efeitos colaterais,
dizendo que sempre existirá apenas uma entrada e apenas uma saída. No
desenvolvimento, nem sempre isso é possível. De fato, isso acontece, sendo
possível nenhuma ou várias entradas e saídas. Muitas vezes, precisamos de
funções impuras para realizar manobras que possibilitem comunicação e
integração dentro do código, por exemplo, randomizações.
9Programação funcional: funções puras
Fonte: Adaptado de Anjana… (2017, documento on-line).
ƛ lambda
Usado para Pensando Programando
Side-effects De jeito nenhum Talvez
Inputs 1 0+
Outputs 1 0+
Fazendo (abstração) ƛx.ƛy.x+y lambda x . y: x + y
lambda x . lambda y: x + y
Usando (aplicação) (ƛx. x + 1) 5
5 + 1
6
(lambda x : x + 1) (5)
5 + 1
6
Quadro 1. Cálculo lambda x expressões lambda
A IPython Development Team criou a ferramenta IPython para facilitar o desenvol-
vimento de programas que utilizam paralelismo. Essa ferramenta traz um ambiente
interativo com arquitetura para computação paralela, conforme você pode conferir
no link a seguir.
http://ipython.org/
Compreensão de listas
Na sua jornada na educação básica, você aprendeu sobre a compreensão
de conjuntos numéricos e como eles são construídos de acordo com regras
específicas. Em programação funcional, existe a compreensão de listas, em
que é possível aplicar funções mais complexas em listas a partir de instruções.
Programação funcional: funções puras10
Vamos considerar uma lista de 1 a 10 em que seja necessário multiplicar
seus elementos por 3. Na linguagem Haskell, por exemplo, isso seria possível
por meio da compreensão de listas, como você pode ver no exemplo:
ghci > [x*2 | x <- [1..10] ] . x
[3,6,9,12,15,18,21,24,27,30]
O que está depois da pipe equivale aos parâmetros, e o que está antes é a
instrução a ser seguida.
Funções currying
Funções em Haskell, assim como outras linguagens funcionais, em geral,
recebem apenas um parâmetro. Existem exceções como a função max em
Haskell, que recebe dois parâmetros e retorna o maior. O conceito de currying
denota uma função que recebe múltiplos argumentos e se transforma em uma
cadeia de funções, cada uma com apenas um parâmetro.
Considere o exemplo utilizando JavaScript para uma soma de dois argumentos em
currying:
const sum2 = (x,y) => x+y;
const curry = f => a => b => f(a, b);
const curry = curry(sum2) (3)(5);
curry;
A função passa dois argumentos e solicita a soma deles, o que traz como saída 8. A
primeira função retorna uma nova função, que, por sua vez, retorna um único resultado.
11Programação funcional: funções puras
ANJANA Vakil — Mary had a little lambda. [S. l.: S. n.], 2017. 1 vídeo (44 min 20 s). Publi-
cado pelo canal EuroPython Conference. Disponível em: https://www.youtube.com/
watch?v=7BsfMMYvGaU. Acesso em: 5 set. 2019.
CHURCH, A. An Unsolvable Problem of Elementary Number Theory. American Journal
of Mathematics, [S. l.], v. 58, n. 2, p. 345–363, Apr. 1936. Disponível em: https://www.
ics.uci.edu/~lopes/teaching/inf212W12/readings/church.pdf. Acesso em: 5 set. 2019.
DU BOIS, A. R. Programação funcional com a Linguagem Haskell. Edinburgh: School of
Mathematical and Computer Sciences, Heriot-Watt University, 2008. 76 p. Disponível em:
http://www.inf.ufpr.br/andrey/ci062/ProgramacaoHaskell.pdf. Acesso em: 5 set. 2019.
MARLOW, S. Parallelism /= concurrency. GHC Mutterings — thought from the develo-
pers of GHC, Glasgow, 6 Oct. 2009. Disponível em: http://ghcmutterings.wordpress.
com/2009/10/06/parallelism-concurrency. Acesso em: 5 set. 2019.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas.
2. ed. Porto Alegre: AMGH, 2009. 630 p.
Leituras recomendadas
BORGES, L. E. Python para desenvolvedores. 2. ed. Rio de Janeiro: Edição do Autor, 2010.
360 p. Disponível em: https://ark4n.wordpress.com/python/. Acesso em: 5 set. 2019.
EVANS, B. Quão funcional é o Java 8? InfoQ Brasil, [S. l.],13 out. 2014. Disponível em:
https://www.infoq.com/br/articles/How-Functional-is-Java-8/. Acesso em: 5 set. 2019.
JAVASCRIPT — Currying. [S. l.: S. n.], 2017. 1 vídeo (12 min 30 s). Publicado pelo canal
Hygor Zorak. Disponível em: https://www.youtube.com/watch?v=19z7FbRk3s8. Acesso
em: 5 set. 2019.
MENDES, E. (Roteiro) Funções #14. GitHub, San Francisco, 21 mar. 2017. Disponível em:
https://github.com/dunossauro/python-funcional/issues/14. Acesso em: 5 set. 2019.
Programação funcional: funções puras12
DICA DO PROFESSOR
Funções puras, basicamente, são aquelas que não produzem side-effects (efeitos colaterais) em
outras funções dentro de um projeto. Para o desenvolvedor, essa mudança requer uma nova
forma de pensar um problema, em que não se pode mais conceber que uma variável mude seu
valor a cada loop de execução da aplicação.
Nesta Dica do Professor, são demonstrados exemplos práticos de implementação de duas
funções (Map e Filter) que auxiliam na rotina de resolução de problemas no código. Elas
permitem mapear e filtrar dados em listas e outras estruturas utilizando expressões lambda.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) As funções puras nos dizem que uma função terá sempre a mesma saída a partir de
uma mesma entrada. Sabendo disso, pense em uma solução para a seguinte questão:
Você é assessor de TI do gabinete de um vereador de sua cidade. Minutos antes de
uma cerimônia, ele solicita que você insira a string "Sr." na frente do nome de todos
os 200 convidados para o evento. Essa lista é extraída do sistema que você administra
e precisa ser deixada na portaria para aguardar a chegada dos convidados.
Qual das alternativas abaixo indica uma função que você utilizaria para resolver essa
situação em nível de código?
A) Função filter.
B) Função map.
C) Função reduce.
D) Função zip.
E) Função currying.
2) A compreensão de listas em programação funcional permite criar soluções de
problemas complexos a partir da manipulação destas. Embora a linguagem Haskell
não seja uma linguagem muito utilizada, é bem fácil de ser interpretada e sua
notação é simples.
Dada a seguinte expressão na linguagem funcional Haskell, identifique a alternativa
que representa o que está sendo pedido por ela:
ghci > [x*2+1 | x <- [1...1000] ] . x
A) Pede que números de 1 a 1000 sejam multiplicados por 2 e somados por 1.
B) Pede que os números 1 e 1000 sejam multiplicados por 2 e somados por 1.
C) Pede que números de 0 a 999 sejam multiplicados por 2 e somados por 1.
D) Pede que números de 1 a 1000 sejam multiplicados por 2 uma única vez.
E) Pede que os números 1 e 1000 sejam elevados ao quadrado e somados por 1.
Davi começou a trabalhar no NTI da Embrapa de sua cidade e está tendo seus
primeiros contatos com linguagens funcionais. Seu chefe disse que ele irá trabalhar
nos projetos de pesquisa genética de gado. Davi, atualmente, programa em Python,
então seu superior lhe deu uma apostila de programação funcional e o seguinte
problema para resolver:
Faça uma função que retorne todos os dados negativos dessa lista, que se refere ao
aumento de peso do gado no último semestre.
3)
Qual das expressões abaixo conseguiria retornar o que foi pedido para Davi?
A) def NumNeg (numeros) : return (list(filter(lambda numero: numero < 0, numeros)))
B) def NumNeg (numeros) : return (list(filter(lambda numero: numero > 0, numeros)))
C) def NumNeg (numeros) : return (list(filter(lambda numero: numero < = 0, numeros)))
D) def NumNeg (numeros) : return (list(reduce(lambda numero: numero < 0, numeros)))
E) def NumNeg (numeros): return (list(filter(lambda numero: numero >= 0, numeros)))
4) Um sistema eficiente tem em suas linhas conceitos que permitem herdar, abstrair e
modificar atributos e métodos. Os conceitos de programação funcional, por meio da
pureza de funções, elevam o nível de abstração de uma aplicação, entregando muita
qualidade.
Nesse sentido, analise qual das alternativas a seguir está correta em relação à função
abaixo:
def analisa_func(elemento, indice):
elementos [indice] +=1
return elementos
A) Trata-se de uma função pura, pois retorna um índice de um elemento que, somado a 1,
apresenta uma saída.
B) Trata-se de uma função impura, pois retorna um índice de um elemento que, somado a 1,
apresenta uma saída.
Trata-se de uma função impura, pois a lista chamada elemento sofre mudança a cada C)
execução da função, conforme o incrementador logo abaixo.
D) Trata-se de uma função pura, pois a lista chamada elemento sofre mudança a cada
execução da função, conforme o incrementador logo abaixo.
E) Trata-se de uma função impura, pois não possui em sua sintaxe um comando lambda e
somente funções que utilizam lambda podem ser puras.
5) Leonardo está desenvolvendo uma aplicação mobile utilizando React. Em um dado
momento do código, ele está implementando um bloco que receberá o somatório de
dois parâmetros e a multiplicação de outro. Qual solução funcional (função) ele pode
implementar para que esse código tenha uma correta implementação e maior
facilidade de verificação de erros?
A) Função filter.
B) Compreensão de listas.
C) Map.
D) Função currying.
E) Função zip.
NA PRÁTICA
Uma linguagem funcional totalmente pura se torna muitas vezes inviável para o desenvolvedor,
tendo em vista que conceitos como herança e mutabilidade de dados são necessários para a
comunicação entre partes do código.
Mesmo assim, otimizar partes do código é fundamental para melhorar a qualidade da
implementação, facilitando correções de erros, testes, etc.
A seguir, você verá a história de Samira, que está informatizando os negócios da família. Ela
passou por uma situação na qual foi importante a implementação de uma função pura, utilizando
a linguagem de programação Python, para a resolução de seu problema.
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Usando a linguagem pFun para a programação de GRIDs
Você ainda tem dúvida de que a programação funcional é uma boa opção? Neste estudo, os
autores confirmam as vantagens das linguagens funcionais no viés do paralelismo.
Conteúdo interativo disponível na plataforma de ensino!
O conceito de tempo nas linguagens de programação
O estudo denota uma cronologia das arquiteturas de computadores e como isso afeta e obriga os
desenvolvedores a repensar seus paradigmas.
Conteúdo interativo disponível na plataforma de ensino!
Software sem bugs, reduzindo falhas em produção com práticas de programação funcional
(em C#)
Um profissional conta sua experiência com a plataforma .NET e de que forma vem aplicando a
programação funcional em sua rotina há mais de duas décadas.
Conteúdo interativo disponível na plataforma de ensino!
Programação funcional: funções de
primeira classe e primeira ordem
APRESENTAÇÃO
O crescimento exponencial das informações produzidas faz com que o mercado do
desenvolvimento se preocupe cada vez mais com a otimização de seus produtos. A tendência
digital aponta cada vez mais para programas rápidos e com uma performance eficaz e,
nessa corrida tecnológica, a programação funcional vem ganhando impulso nos últimos
anos. Seus conceitos estão sendo cada vez mais utilizados por linguagens que até então eram
puramente imperativas e orientadas a objetos. Códigos puros, imutabilidade e ausência de estado
estão cada vez mais presentes nas implementações como forma de otimizar os projetos de
software.
Nesta Unidade de Aprendizagem, você aprenderá sobre como as funções de primeira classe e
primeira ordem auxiliam na otimização de códigos e por que hoje em dia é tão importante que
se entenda a programação funcional, as suas vantagens e a capacidade de interoperabilidade em
códigos orientados a objetos.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Explicar o que são funções de primeira classe. •
Identificar as funções de primeira ordem. •
Aplicar funções de primeira classe e primeira ordem.•
DESAFIO
Funções de primeira ordem têm como premissa principal a capacidade de uma função poder ser
tratada como um valor qualquer dentro de uma estrutura. Ela pode ser um argumento, um
resultado que pode ser passado ou manipulado nesse escopo.
Você é informata em uma escola técnica de sua cidade e está desenvolvendo um sistema para o
processamento das notas dos alunos. Dentre as funcionalidades requisitadas pela diretora da
escola, você precisa implementar um bloco de instruções que verifique as notas dos alunos de
cada turma e diga quais alunos atingiram a média, que é 7.
Utilizando a linguagem Python, como você escreveria uma função de primeira classe para
resolver esse problema? Considere um número máximo de 50 alunos para as notas inseridas.
INFOGRÁFICO
Uma linguagem de programação funcional constitui uma estrutura que permite ao
programador utilizar funções que garantam a pureza, a imutabilidade e a ausência de
estado dentro de seu escopo. Algumas funções, conhecidas como funções de ordem superior,
permitem manipular listas e executar ações aos seus elementos, sem a necessidade da recursão e
da mutabilidade. Isso também auxilia para que linguagens não funcionais implementem funções
de primeira ordem em sua estrutura, como é o caso da linguagem Python.
Funções como Map e Filter auxiliam nessa construção de código funcional, mas você sabia que
além de utilizar cada uma separadamente, se unirmos as suas funcionalidades conseguimos
resolver problemas ainda mais complexos? Veja no Infográfico:
CONTEÚDO DO LIVRO
A programação funcional só pode ser chamada assim quando aplica conceitos básicos que
caracterizam esse paradigma, como, por exemplo, imutabilidade, ausência de estados, funções
como objetos de primeira classe e outros. No escopo das funções como objetos de primeira
classe e ordem superior, é necessário que seja possível que uma função se comporte como
qualquer outro objeto e que ela possa ser passada ou retornada dentro de outras funções.
No capítulo Programação funcional: funções de primeira classe e primeira ordem, você
entenderá como funcionam e quais são as características das funções de primeira classe e
primeira ordem dentro da programação funcional.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Marcia Cristina Domingues Leite
Programação funcional:
funções de primeira
classe e primeira ordem
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Explicar o que são funções de primeira classe.
� Identificar funções de primeira ordem.
� Aplicar funções de primeira classe e primeira ordem.
Introdução
No âmbito da computação, o paradigma imperativo, defendido pela
orientação a objetos, é o mais utilizado e conhecido. Entretanto, desde
1930, Alonzo Church defende o uso de funções matemáticas para a reso-
lução de problemas computacionais. No escopo de Church, conhecido
como programação funcional, o principal método para se estruturar o
programa é pela definição e aplicação de funções.
Tal experiência compreende uma nova forma de programar e exercitar
a escrita de bons códigos, lidando com expressões, algoritmos e funções
baseados no cálculo lambda. A programação funcional não deve ser
considerada oposta à programação orientada a objetos, embora sejam
muito diferentes. As duas linguagens podem e devem ser utilizadas
em uma mesma aplicação, pois no mercado atual existem muitos tipos
de linguagem multiparadigma. Essa utilização “híbrida”potencializa o
nível da aplicação, conferindo performance, economia e inúmeras outras
características ao programa.
Neste capítulo, você aprenderá sobre a programação funcional, prin-
cipalmente no que diz respeito às funções de primeira classe e primeira
ordem ou ordem superior, como são mais conhecidas. Serão abordados
os principais conceitos e metodologias aplicadas, que fazem com que es-
tas funções tenham essa classificação, com o auxílio de exemplos práticos.
Conceituando funções de primeira classe
(first-class functions)
Sebesta (2018) define um programa funcional como uma coleção de funções
que, quando bem definidas, culminam em um programa mais simples. De
modo geral, funções anônimas recebem em sua sintaxe a palavra lambda, pois
utilizam os conceitos do cálculo de Church, conforme o exemplo:
(lambda (x) (* x x))
Isso não significa que a programação funcional não pode ser empregada
em blocos de código não anônimos. Os conceitos deste paradigma, quando
empregados, denotam códigos simplificados, imutáveis e que não produzem
efeitos fora da função.
As funções, além de serem executadas dentro de seu escopo, podem ser
passadas como argumento para outras funções, ser retornadas como valor de
outras funções ou, ainda, ser armazenadas em estruturas de dados. Portanto,
pode-se fazer uma nova operação utilizando uma função (ABELSON; SUS-
SMAN, 1984). Todas essas possibilidades e características descrevem uma
função como sendo de primeira classe ( first-class function).
A utilização de funções de primeira classe é uma prática padrão em pro-
gramas cujo paradigma utilizado é o funcional.
Uma função de primeira classe pode se comportar como tipo de objeto ou
qualquer parâmetro dentro de outras funções, conforme o exemplo:
>> funcao = lamba x: x
>> def segunda _ funcao (x):
return x + 10
lista = [funcao, segunda _ funcao]
print (lista)
O exemplo demonstra uma função anônima lambda armazenada na va-
riável funcao. Em seguida, uma lista armazena a função anônima e uma
função def declarada. Ou seja, ela é passada como argumento em um bloco
de instrução e poderá servir de parâmetro para outras instruções do projeto.
Programação funcional: funções de primeira classe e primeira ordem2
Nos Estados Unidos, utiliza-se o termo “cidadão de primeira classe” para definir uma
pessoa que pode ir e vir para qualquer lugar e fazer o que quiser. Essa analogia é
utilizada em relação às funções de primeira classe, pois a ideia é, justamente, que
uma função possa ser qualquer coisa (parâmetro, argumento, resultado) dentro de
um bloco de instruções.
Funções anônimas
Funções anônimas são funções que podem ser declaradas em qualquer contexto
e não precisam necessariamente ter um nome. Em linguagens que suportam
esse tipo de função é possível passá-las como argumento para as chamadas
funções de ordem superior.
Esse tipo de função geralmente utiliza funções anônimas que especificam
os parâmetros e a definição de uma função, sendo também conhecidas como
expressões lambda, muito utilizadas no paradigma funcional (BORGES, 2010).
Para que possamos, por exemplo, calcular a média dos valores de uma lista
qualquer, podemos utilizar uma expressão lambda:
minha _ lista = [0,1,2,3,4,5,6,7,8,9,10]
media = lambda valor: sum(valor) / len (valor)
media (valor)
A saída desta expressão será 5. A variável média recebe uma função
lambda que, segundo Tucker e Noonan (2009), específica seus parâmetros e
definições sem especificar seu nome, o que explica seu conceito de anônima.
Essas funções, em conjunto com iteradores e geradores, permitem a perfeita
implementação de códigos do paradigma funcional.
3Programação funcional: funções de primeira classe e primeira ordem
Listas
Lott (2015) explica que na linguagem de programação Python as listas são
iteráveis, ou seja, são objetos sequenciais que podem ser submetidos a ite-
rações. Podemos utilizar uma tupla para coletar a saída de uma expressão
ou, até mesmo, uma lista simples, que utilizando os colchetes forma um
gerador. A Figura 1 demonstra, de forma adaptada, a diferença sutil entre
uma compreensão de listas e um gerador.
Figura 1. Diferença entre uma compreensão de listas e um
gerador.
Fonte: Adaptada de Lott (2015).
O range (intervalo) demonstrado nas linhas 1, 2 e 3 da Figura 1 é lento e
não produzirá nenhum resultado até que passe pela estrutura que irá iterá-
-lo. A quinta linha denota de que forma o range poderá ser iterado por uma
estrutura de decisão (neste caso um for) ou algo semelhante, para que ele
possa produzir uma saída. Na penúltima linha da Figura 1 (linha 7) temos
uma compreensão de lista, que recebe uma função list para gerar uma nova
lista a partir dos elementos iterados.
Funções de ordem superior
(High-order functions)
Funções de primeira ordem ou de ordem superior são também conhecidas
como HOFs. Lott (2015) define, de forma bastante prática, o que constitui
uma função de ordem superior:
Programação funcional: funções de primeira classe e primeira ordem4
� uma função que recebe uma função;
� uma função que retorna uma função;
� uma função que recebe e retorna uma função.
A linguagem Python e outras linguagens, como JavaScript, Haskell e C#,
possuem algumas funções que são consideradas de ordem superior, conforme
veremos a seguir.
Funções aninhadas
Burstall (2000) explica que funções são flexíveis a ponto de ser capazes de
retornar como parâmetros ou como objetos de outras funções. Uma função
aninhada tem acesso ao ambiente em que foi criada. Vejamos o exemplo a
seguir.
def soma (x, y, z, b):
def soma _ dois(x1, x2):
return x1+x2
return x + y + soma _ dois (z, b)
>>> soma (1,2,3,4)
>>> 10
No exemplo, temos a função soma_dois dentro da função soma. Neste
exemplo é possível visualizar que o retorno será o somatório dos dois primeiros
parâmetros da função soma com os dois parâmetros da função soma_dois.
Em outras palavras, trata-se de uma função dentro de outra função.
Funções embutidas (built-in functions)
Funções embutidas são funções prontas, disponibilizadas pelas linguagens de
programação em que não precisamos realizar instruções para que algo seja feito.
Na linguagem Python, por exemplo, se digitarmos print("Olá
mundo!"), significa que a função print é responsável por mostrar na tela
a string digitada.
A função map é um exemplo clássico de função embutida ou interna de
ordem superior. Tem como principal função permitir que uma determinada
estrutura de dados (lista, array, tupla) seja varrida e a instrução declarada
seja executada em cada elemento, o número de vezes necessário para que a
5Programação funcional: funções de primeira classe e primeira ordem
condição seja satisfeita. Esta função pode ser passada como parâmetro de
uma variável, ser recebida em uma função etc. A partir dessa varredura será
gerado um novo array, contendo os elementos resultantes dessa execução
(TUCKER; NOONAN, 2009). A Figura 2 exemplifica a utilização da função
map na linguagem Python.
Figura 2. Função map.
A Figura 2 demonstra um exemplo da função map sendo utilizada para
varrer o array “numeros” e calcular a raiz quadrada (square root) de todos
os elementos da lista. Ao final, uma nova lista com os resultados é gerada.
Esta lista é retornada como resultado da função map, portanto, uma função
de ordem superior.
Outro exemplo é a função filter. Ramalho (2015) explica que tal função
retorna uma nova lista na qual os elementos são resultados daqueles filtrados
na execução da função filter.
Como exemplo, vamos solicitar que sejam filtrados da lista 1 apenas os
valores múltiplos de 5:
>>>Lista _ 1 = [1, 2, 3, 4, 5, 6, 7, 10, 15, 33, 25, 50, 46, 125,
500, 324]
>>>multiplos _ 5 = list(filter(lambda x: x % 5 == 0, Lista _ 1))
>>>print (multiplos _ 5)
A saída será:
[5, 10, 15, 25, 50, 125, 500]
Programação funcional: funções de primeira classe e primeira ordem6
Conceitualmente, uma High Order Function, ou função de ordem superior, depende
defunções como objeto de primeira classe para ser verdadeira. Embora algumas
linguagens não possuam funções de primeira classe, como a linguagem C, estas
permitem a criação de funções de ordem superior pelo uso de ponteiros.
A função reduce, como o próprio nome sugere, é muito utilizada quando
precisamos reduzir os elementos de uma lista a um único valor. Tudo que for
executado dentro desta função será agregado, até que se torne apenas um
elemento (BORGES, 2014).
Vamos utilizar como exemplo a mesma estrutura vista na função map.
Apenas trocando a condição para soma e a função para reduce, teremos
o seguinte:
>>> from functools import reduce
>>> Lista _ 1 = [1,2,3,4,5,6,7,10,15,25,50,46,125,500,324]
>>> soma = reduce ((lambda x, y: x+y), Lista _ 1)
>>> print (soma)
A saída será:
1123
A expressão lambda retornará o resultado da soma de todos os elementos
do array que foram reduzidos a um só elemento.
Operadores
Embora saibamos que as funções de ordem superior permitem diversas funcio-
nalidades dentro de um código, precisamos ter em mente que, muitas vezes, a
escrita de uma função se torna extensa, o que pode dificultar o entendimento
do desenvolvedor ou analista de projeto.
Sendo assim, os operadores servem para abstrair ainda mais o código,
reduzindo informações e instruções de modo que o entendimento se torne
ainda maior.
7Programação funcional: funções de primeira classe e primeira ordem
Vamos verificar o exemplo em Python. Dada a lista, vamos reduzir os
elementos a apenas um valor. Na forma com a qual estamos acostumados,
teríamos as seguintes linhas de código:
from operator import add
from functools import reduce
print (reduce(lambda x , y: x + y, [1,2,3,4,5])
Para simplificar essa linha de código, podemos utilizar um operador, que
irá reduzir toda a escrita lambda a apenas uma palavra:
print (reduce(add, [1,2,3,4,5]))
A saída em ambos os casos seria a mesma, no caso, 15.
Existem diversos operadores que podem ser utilizados nesses casos, como
add (soma), sub (subtração), mul (multiplicação), not (negação), true
(sentença verdadeira), que podem ser utilizados conforme a necessidade do
desenvolvedor.
Implementando funções de primeira classe e
de ordem superior
Funções são blocos de instruções que podem ser executados a qualquer mo-
mento, em qualquer parte de um determinado código. Existem funções que
possuem nome e as chamadas funções anônimas, que auxiliam em situações
específicas. Outra premissa é que nem sempre uma função receberá ou re-
tornará valores.
Como visto anteriormente, dizemos que uma função é de primeira classe
quando esta pode ser um objeto qualquer dentro de determinada função (um
valor, um resultado, um parâmetro etc.). O exemplo mais simples que utiliza-
mos para pensar uma função na linguagem Python como objeto de primeira
classe é a função soma:
>>> soma = lambda x, y : x + y
>>> soma (5,6)
>>> 11
Programação funcional: funções de primeira classe e primeira ordem8
Neste exemplo, a função soma pode ser passada como argumento para
outras funções, conforme dado a seguir:
>>>> def pares (numeros): return list(filter(lambda numero:
numero > 0, numeros))
>>>> print pares ([1, -2, -3, soma (5,6)])
>>> [1, 11]
Neste exemplo, utilizamos a função de ordem superior filter para ve-
rificar se os números do array são positivos. Além disso, passamos a função
soma deste exemplo como parâmetro para ser verificado.
Outro exemplo de funções sendo retornadas como argumento de funções
são as funções de ordem superior. Na linguagem Python, podemos utilizar
como exemplo as funções reduce, map e filter.
>>> func = reduce (lambda x, y: x * y, [30,50,100])
>>> print (func)
>>> 150000
Este exemplo demonstra uma função que toma como argumento a função
reduce para reduzir a expressão lambda a apenas um valor.
Utilizando operadores e tomando como exemplo os mesmos valores utili-
zados anteriormente é possível otimizar o último código apresentado.
from operator import add, sub, mul
from functools import reduce
>>> func = (reduce (add, [30,50,100]),
>>> reduce (sub, [30,50,100]),
>>> reduce (mul, [30,50,100]))
>>> print (func)
Como saída, teríamos:
>>> (180, -120, 150000)
O exemplo demonstra que é possível reduzir a expressão lambda por meio
de operadores, que nada mais são do que módulos que permitem construir
chamadas, assumindo objetos iteráveis dentro de uma estrutura de código.
9Programação funcional: funções de primeira classe e primeira ordem
Na prática, utilizar operadores faz com que a legibilidade do código seja
maior, uma vez que abrimos mão de incógnitas (x, y, z, b, a) e inserimos
comandos intuitivos, como add, mul, or, not, is not.
É importante destacar que diversas linguagens possuem operadores e,
semanticamente, a funcionalidade destes é a mesma, mudando apenas a sintaxe,
que varia de acordo com a linguagem de programação.
Podemos passar uma função como argumento de outra função, conforme
vemos a seguir:
>>> def func (x):
>>>return x + 2
>>> list (map(func, [1,2,3]))
Neste exemplo, declaramos a função func, que recebe x como parâmetro
e deve retornar o somatório de x com 2. Na sequência, uma função anônima
map toma a função func como parâmetro e instrui que x receba os valores
no vetor ao lado. Como saída teríamos, respectivamente: 3, 4 e 5.
Como forma de demonstrar com mais clareza sobre as principais funções
de ordem superior internas na linguagem Python, o Quadro 1 apresenta o
nome e o que esta realiza dentro do escopo da função.
Fonte: Adaptado de Kuchling ([2019]).
Função O que realiza
map Aplica a instrução em cada elemento da lista.
filter Filtra os elementos indicados na instrução.
reduce Reduz os elementos da lista a um único valor,
de acordo com a operação declarada.
sorted Ordena os elementos da lista, de acordo
com a instrução declarada.
max Busca o maior valor entre os elementos.
min Busca o menor valor entre os elementos.
Quadro 1. Principais funções de ordem superior embutidas ou internas de Python
Programação funcional: funções de primeira classe e primeira ordem10
As funções descritas são de ordem superior, pois, resumidamente, per-
mitem uma função dentro de outra função, ou uma função como resultado
de outra função.
ABELSON, H.; SUSSMAN, G. J. 1985. Structure and interpretation of computer programs.
Cambridge: MIT Press; New York: McGraw-Hill, 1985. 542 p.
BORGES, L. E. Python para desenvolvedores. 2. ed. Rio de Janeiro: Edição do Autor, 2010.
360 p. Disponível em: https://ark4n.wordpress.com/python/. Acesso em: 23 set. 2019.
BORGES, L. E. Python para desenvolvedores: aborda Python 3.3. 3. ed. São Paulo: Novatec,
2014. 320 p.
BURSTALL, R. Christopher Strachey — Understanding Programming Languages. Higher-
-Order and Symbolic Computation, [S. l.], v. 13, n. 1–2, p. 51–55, Apr. 2000.
KUCHLING, A. M. Functional Programming HOWTO. Python Software Foundation, [S.
l.], [2019]. Disponível em: https://docs.python.org/2/howto/functional.html. Acesso
em: 23 set. 2019.
LOTT, S. Functional Python programming. Birmingham: Packt Publishing, 2015. 360 p.
RAMALHO, L. Python fluente: programação clara, concisa e eficaz. São Paulo: Novatec,
2015. 800 p.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2.
ed. Porto Alegre: AMGH, 2009. 630 p.
Leitura recomendada
SCHADE, G. Exercícios para expressões lambda. GitHub, San Francisco, 26 jun. 2018.
Disponível em: https://github.com/gabrielschade/Python-Intro-Serie/blob/master/09-
-Funcoes-2.py. Acesso em: 23 set. 2019.
11Programação funcional: funções de primeira classe e primeira ordem
DICA DO PROFESSOR
O paradigma funcional permite a escrita de linhas de forma mais resumida, com abstração
elevada a um nível maior. Entretanto, é importante destacar que, na maioria das vezes,
precisamos utilizar mais de um paradigma além do funcional para que o sistema sejaconsiderado eficiente. Uma ferramenta que facilita nosso entendimento das linhas de códigos
escritas durante o projeto são os operators. Estes operadores substituem expressões, realizando a
mesma função delas e simplificando o entendimento do código.
A Dica do Professor mostra o itemgetter, um operador que pode ser utilizado para substituir
instruções com a mesma funcionalidade. Confira a seguir:
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) A programação funcional contém alguns conceitos básicos que caracterizam a sua
forma de resolver problemas computacionais. Pureza, funções anônimas,
imutabilidade, funções como objeto de primeira classe e de ordem superior são só
algumas particularidades desse paradigma.
Baseado nas premissas e dada a função em Java Script, assinale a alternativa correta
quanto à característica/classificação dessa função:
var minhaVar = function minhaFunc () {
};
console.log(minhaVar);
A) Função de primeira classe.
B) Função de alta ordem.
C) Função anônima.
D) Função lambda.
E) Função Map.
2) Sabe-se que as funções podem ser repassadas como argumento de outras funções, e a
esse tipo damos o nome de High Order Functions (Funções de Ordem Superior).
Sabendo disso, imagine o seguinte cenário:
Você trabalha em um escritório e cuida a gestão de TI de toda a empresa. Você
precisa gerar um relatório e verifica que os valores estão invertidos e que você
precisa revertê-los.
Marque a alternativa que corresponde à função de ordem superior capaz de resolver
essa questão, dada a seguinte lista com os dados a serem revertidos:
[[135 , 335], [228 , 336], [345 , 478], [459 , 115], [552 , 636]]
A) lista = [[135 , 335], [228 , 336], [345 , 478], [459 , 115], [552 , 636]]
def func_rev(x):
return list(reversed(x))
list(filter(func_rev, lista))
B) lista = [[135 , 335], [228 , 336], [345 , 478], [459 , 115], [552 , 636]]
def func_rev(x):
return list(reversed(x))
list(map(func_rev, lista))
C) lista = [[135 , 335], [228 , 336], [345 , 478], [459 , 115], [552 , 636]]
def func_rev(x):
return list(reversed(x))
list(map(x, lista))
D) lista = [[135 , 335], [228 , 336], [345 , 478], [459 , 115], [552 , 636]]
def func_rev(x):
return list(reversed(lista))
list(map(func_rev, lista))
E) lista = [[135 , 335], [228 , 336], [345 , 478], [459 , 115], [552 , 636]]
def func_rev(x):
return lista(reversed(x))
list(map(func_rev, lista))
3) Você é desenvolvedor júnior de uma empresa e está trabalhando em um sistema para
uma livraria. Terminado o CRUD (Create, Read, Update, Delete) que irá permitir aos
usuários cadastrar todos os livros do estabelecimento, você percebeu que precisa
fazer com que os dados sejam ordenados alfabeticamente para a emissão de
relatórios.
Qual função de ordem superior você utilizaria para fazer isso?
A) Função Map.
B) Função Zip.
C) Função Sorted.
D) Função Reduce.
E) Função Filter.
4) Funções representam uma importante parte da Programação Funcional. Elas podem
ser definidas dentro de um bloco de código de outras funções e também podem ser
retornadas a partir das chamadas de outras funções.
Dada a função a seguir em Python, a partir dos conceitos estudados nesta Unidade de
Aprendizagem, marque a alternativa que assinala o resultado de sua execução:
lista_1 = [6, 7, 8, 9]
lista_2 = [1, 2, 3, 4]
for x in zip (lista_1, lista_2):
print(x)
A) (6, 1)
(7, 2)
(8, 3)
(9, 4)
B) (6, 7)
(7, 9)
(1, 2)
(3, 4)
C) (6, 9)
(7, 2)
(8, 3)
(1, 4)
D) (6, 7)
(1, 2)
(9, 3)
(8, 4)
E) (6, 3)
(7, 2)
(8, 1)
(9, 4)
5) Operadores são importantes módulos que permitem que blocos de instruções fiquem
fáceis e legíveis. Tratando-se de linguagens multiparadigmas, em que podemos
utilizar funções anônimas lambda, esses operadores substituem de forma prática os
parâmetros compostos por letras e operadores.
Dada a expressão lambda de soma, utilize um operador correspondente na linguagem
Python, que irá substituir sem que a função perca a sua característica e saída:
>>> adicao= lambda x, y : x + y
>>> print (soma (5,6))
>>> 11
A) print (map(add, [5,6]))
B) print (reduce(lambda: mul, [5,6]))
C) print (reduce(mul, [5,6]))
D) print (reduce(lambda: add, [5,6]))
E) print (reduce(add, [5,6]))
NA PRÁTICA
Conceitos de programação funcional permitem a abstração do código reduzindo linhas e
otimizando o projeto. Funções de primeira classe e de alta ordem permitem atribuição de
funções, como valores ou recebimento, e retorno de funções em outras funções.
Na Prática mostra a experiência de Gilberto no desenvolvimento de uma calculadora para um
cliente da empresa em que trabalha. Ele utilizou conceitos do paradigma funcional para entregar
a aplicação ao cliente.
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Uma introdução à programação em Lua
São diversas as linguagens de programação funcional existentes, algumas mais conhecidas e
outras nem tanto. O estudo demonstra a linguagem Lua, muito utilizada no desenvolvimento de
jogos e as suas principais características.
Conteúdo interativo disponível na plataforma de ensino!
A linguagem de programação funcional Sloth
Algumas linguagens têm funções bem definidas no escopo funcional. A linguagem Sloth tem
como característica a possibilidade de servir para testes de compilação de outras linguagens
funcionais. Confira, neste estudo, as características e o projeto que envolvem essa linguagem.
Conteúdo interativo disponível na plataforma de ensino!
Programação funcional: functors,
aplicative functors e monads
APRESENTAÇÃO
O Paradigma Funcional corresponde a novas formas de resolver problemas computacionais,
uma vez que, diferentemente da programação imperativa, diz ao programa o que deve ser
feito, e como as coisas são, de modo que tudo seja expresso em forma de funções.
Algumas linguagens implementam a programação funcional em sua forma mais pura,
como Haskell, Scalla, Closure e Erlang. Outras linguagens são consideradas não funcionais
por conterem características de mutabilidade, embora contenham conceitos de high order
functions (funções de ordem superior), que permitem implementar blocos funcionais dentro do
projeto, como, por exemplo, Python, Ruby, Java 8, etc.
Nesta Unidade de Aprendizagem, você irá acompanhar alguns conceitos introduzidos
pela programação funcional que se mostram importantes dentro do escopo da pureza de código.
Será possível compreender alguns conceitos capazes de abstrair ainda mais um código e, dentre
esses, destacam-se os functors, aplicative functors e monads.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Determinar o que são functors. •
Definir os aplicative functors. •
Reconhecer monads na programação funcional. •
DESAFIO
Em um primeiro momento, conceitos como funtores e mônadas podem assustar quem está
começando a entender a programação funcional. Mas, na verdade, funtores são nada mais
que tipos que podem ser mapeados. No entanto, o uso de mônadas facilita a legibilidade de
uma notação matemática no contexto computacional.
Nesse sentido, imagine a seguinte situação:
Você trabalha como desenvolvedor Haskell home service e, atualmente, trabalha em um projeto
de uma artesã que fabrica artigos com feltro. As quantidades do material que ela tem em estoque
são lançadas no sistema e vão para uma lista. A artesã tinha 5 metros de feltro azul e,
recentemente, recebeu pelo correio mais 4 metros.
Utilize a linguagem Haskell e os conceitos de funtores para inserir essa quantidade apenas no
item que corresponde à quantidade de feltro azul (o valor 5), preservando o valor dos demais
itens de lista.
Considere os itens da lista [1,2,3,4,5,6,7].
INFOGRÁFICO
Functors e monads tratam de conceitosque permitem entender valores que contêm contextos e
comportamentos que podem ser mapeados e aplicados em diferentes funções. O resultado disso
será um novo valor do mesmo tipo, mas com um novo contexto.
O Infográfico demonstra, de uma forma mais simples, o que são functors e monads no contexto
computacional.
CONTEÚDO DO LIVRO
A programação funcional é, em suma, um paradigma norteado pela ideia da aplicação de
funções matemáticas para a resolução de problemas. Seguindo essa mesma linha, as mônadas e
os funtores também têm a sua funcionalidade baseada em outra teoria matemática, a das
Categorias.
No capítulo Programação funcional: functors, aplicative functors e monads, da obra Paradigmas
de programação, você aprenderá um pouco mais sobre esses conceitos, que em um primeiro
momento podem parecer complexos, mas que fazem parte da rotina de programação e
apresentam a ideia de melhoramento de códigos por conta das abstrações.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Marcia Cristina Domingues Leite
Programação funcional:
functors, applicative
functors e monads
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Determinar functors.
� Definir applicative functors.
� Reconhecer monads na programação funcional.
Introdução
A programação funcional instituiu uma nova forma de pensar e construir
soluções para problemas computacionais. Esse paradigma se estrutura
a partir de conceitos contrários aos já experimentados, que vão desde
imutabilidade, ausência de estados, funções de ordem superior, funções
puras e maior nível de abstração, até conceitos mais desconhecidos e
avançados.
Embora a ideia central do paradigma funcional seja a construção de
funções pequenas, simples e fáceis de testar, conceitos mais avançados
permitem um maior nível de complexidade na utilização desse tipo de
programação.
Composição de funções, functors, applicative functors e monads são
conceitos mais abstratos e difíceis de ser compreendidos, entretanto,
estes são recorrentes na vida do desenvolvedor.
Neste capítulo, você estudará conceitos do paradigma funcional,
características e comportamento dos functors, applicative functors e mo-
nads. Os três termos serão aqui tratados em português, respectivamente,
como funtores, funtores aplicativos e mônadas.
Funtores
A programação funcional tem como preceito a orientação a funções, o que faz
com que toda sua estrutura seja baseada na aplicação de funções matemáticas
implementadas pelo cálculo lambda de Church (1941).
Conceitos como pureza e inexistência de side effects (efeitos colaterais) são
os mais conhecidos, entretanto existem conceitos mais abstratos e complexos
que envolvem linguagens de programação funcional. A linguagem de progra-
mação Haskell é um exemplo disso, tendo em sua estrutura uma tipagem forte,
que convida o desenvolvedor a um estudo aprofundado de outros conceitos
para sua utilização.
Primeiras noções de funtores
Oliveira (2017) esclarece que a palavra functor tem sua origem na matemática,
especificamente, na teoria das categorias, pela qual a linguagem Haskell
norteia seus conceitos de programação. O autor explica que essa teoria já é
amplamente utilizada na engenharia de software em outros países e que a
expectativa é que esta se torne uma realidade também no Brasil.
Ainda, segundo Oliveira (2017), categorias são, em suma, estruturas abs-
tratas que possuem objetos e comportamentos. O autor destaca que todos os
elementos e morfismos criados possuem relação entre si e que aqueles que não
possuem relação são denominados neutros, constituindo a função identidade.
Em toda categoria existe pelo menos uma função identidade e, a partir dela,
outras funções são geradas.
Para explicar categorias no âmbito de banco de dados, Spivak (2014) faz
uma analogia a esse conceito, comparando os objetos às tabelas que compõem
um banco de dados. Em relação aos morfismos ou comportamentos, o autor
os equipara às colunas que fazem parte de cada tabela. A Figura 1 ilustra o
que seriam objetos e comportamentos.
Programação funcional: functors, applicative functors e monads2
Figura 1. Exemplo de objetos e comportamentos.
Fonte: Oliveira (2017, p. 89).
Cada tabela dentro de uma estrutura de banco de dados será um objeto a
ser programado, e suas colunas dizem de que forma irá se comportar, além
de quais parâmetros deverá receber, armazenar ou informar ao usuário. Outro
detalhe importante é que cada categoria é composta por tipos (strings, inteiros,
etc.) e por operadores e funções.
Os funtores suportam o mapeamento, respeitando a identidade e as com-
posições, ou seja, seus componentes podem ser repassados a outras funções,
desde que sua identidade seja respeitada. Eles constituem classes (ou type-
classes) que possuem a função fmap, que realiza o mapeamento desta função,
transformando-a em um determinado valor, sendo capaz de retirá-las de um
contêiner e inserir em outro, como será visto mais adiante, quando tratarmos
de mônadas.
O exemplo a seguir, em Haskell, demonstra, de forma prática, como ocorre
a declaração de um funtor que utiliza a função fmap.
Prelude >:t fmap
fmap :: (Functor f) => (a -> b) -> f a -> f b
Neste caso, fmap recebe uma função a b dentro de um contêiner f e
deverá retornar um elemento do tipo f b.
3Programação funcional: functors, applicative functors e monads
Funtor maybe
Esse tipo de funtor permite que as instruções sejam realizadas partindo do pres-
suposto que pode ou não haver um valor dentro do contêiner. Veja o exemplo:
minha _ funcao :: divisao - > divisao -> Maybe divisao
minha _ funcao a 0 = Nothing
minha _ funcao a b = Just (a/b)
A função minha_funcao recebe dois parâmetros que serão testados
e, caso o segundo parâmetro (divisão por zero) seja 0, retornará Nothing.
Na sequência, utiliza-se o constructor Just, que realizará uma operação
válida. Implementando o fmap e introduzindo valores, podemos testar da
seguinte maneira:
Prelude -> fmap (2*) (minha _ funcao 2 0)
Nothing
Dessa forma, é possível tratar situações indesejadas, evitando erros encade-
ados em decorrência da reutilização de funções em diversas partes do código.
Utilizando o operador <$> é possível declara o funtor fmap dentro de uma função.
Essa utilização é chamada de modo infixo e é muito utilizada em funtores aplicativos.
Podemos observá-la no exemplo a seguir (ARAÚJO; ACIÓLY, 2008):
Prelude (2*) <$> (minha _ funcao 50 5)
Just 20
Basicamente, os funtores possibilitam que as funções sejam operadas,
pois é por meio deles que o acesso aos contêineres ou rótulos que armazenam
valores e comportamentos se torna computável, como vimos anteriormente.
Programação funcional: functors, applicative functors e monads4
Funtores aplicativos
Paterson (2012) afirma que a notação de um funtor é definida da seguinte
forma, na linguagem Haskell:
class Functor f where
fmap :: (a -> b) -> f a -> f b
O autor relata que as instâncias de um funtor possuem variados conceitos
computacionais e, dentre estes, os contêineres pelos quais o mapa modifica
os elementos, preservando seu comportamento. Outra classe de instâncias
são as chamadas noções de computação, dentre as quais estão as mônadas e
os funtores aplicativos.
As funções costumam receber um parâmetro e retornar outro. Visualmente,
pensamos muitas vezes que uma função possui mais de um parâmetro, quando
na verdade ela apresenta apenas um parâmetro e este pode retornar outra
função, como, por exemplo:
x -> y -> z
Pode parecer que a função recebe x e y e retorna z, mas, na verdade,
ela recebe x e retorna uma função b -> c, ou seja, f(x) y -> c. Isso
permite que possamos passar apenas alguns argumentos de uma função ou,
até mesmo, passar uma função como argumento de outra.
Oliveira (2017) relata que, quando é necessário operar uma função dentro
de um funtor, existe a necessidade de se utilizar o operador <*> da classe
Applicative, que norteia as operações utilizandoos funtores aplicativos.
Na seção anterior, foram apresentados exemplos de funtores que utilizam
apenas um parâmetro para mapear uma função. Ao mapear funções que
possuem mais de um parâmetro, teremos funtores que terão funções dentro de
sua estrutura. Parece confuso, mas se formos mapear uma função que assume
outra função como parâmetro, teríamos algo como:
($) :: (x -> y) -> x -> y
<*> :: f (x -> y) -> f x - > f y
Na primeira linha, estamos trabalhando com o funtor fmap($); já na
segunda linha, vemos um funtor aplicativo (<*>) recebendo uma função, que
recebe outra função como parâmetro.
5Programação funcional: functors, applicative functors e monads
Para que possamos utilizar funtores aplicativos na linguagem Haskell é
necessário importar o módulo Control.Applicative.
Muitos estudos dizem que um funtor aplicativo possui mais recursos que
um funtor e menos recursos que uma mônada, sendo considerado um inter-
mediário entre os dois.
Um exemplo bastante prático dessa questão seria uma simples inserção de
texto em um programa. Geralmente, utilizamos uma mônada IO, que realiza
computações a partir de uma entrada de dados, nos entregando uma saída.
No entanto, com um funtor aplicativo é possível implementar uma solução
da seguinte forma:
main = IO ( )
do texto < - getLine
if null texto
then putStrLn "Você não digitou nada"
else putStrLn ("obrigada por digitar" ++ text)
Este exemplo mostra uma abstração que utiliza a notação do e a mônada
IO. Quando inserimos a função do na linha da função getLine, realizamos
um encadeamento de ações, pois estamos rodando a função de dentro da
getLine, que é a entrada de texto para o usuário.
Funtores aplicativos são abstrações úteis em código funcionais, mas tam-
bém em códigos de linguagens não funcionais, como no caso da linguagem
C#. É possível dizer que funtores mapeiam uma função, enquanto funtores
aplicativos mapeiam funções utilizando funções.
Capriotti e Kaposi (2014) demonstram que funtores aplicativos são definidos
pela seguinte typeclass:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a ->b) -> f a -> f b
Os autores destacam que a utilização desta computação permite que duas
funções sejam relacionadas, aplicando uma função retornada pela primeira
ao valor retornado pela segunda. Vale destacar que, nesses casos, dizemos
que precisamos aplicar uma função a um valor no qual ambos estão encap-
sulados, o que gerará um terceiro valor, também encapsulado. Esses valores
são encapsulados pela função pure.
Programação funcional: functors, applicative functors e monads6
Assim como em funtores, podemos aplicar uma instância Maybe em um
funtor aplicativo. A notação seria a seguinte:
instance Applicative Maybe where
pure x = Just x
Nothing <*> _ = Nothing
(Just f) <*> something = fmap f something
Neste exemplo, a partir da definição da classe, o f passa a desempenhar
o papel de funtor aplicativo, que deve assumir um tipo concreto como parâ-
metro. Por esse motivo, declaramos a instância Applicative Maybe. Já
sabemos que a função pure é responsável por encapsular algo em um funtor
aplicativo, por isso dizemos que é igual a Just x, pois caso não igualasse,
o Just x seria apenas um funtor normal. Em seguida, declaramos que, caso
algo extraído da função for igual, inexistente ou zero (considerado Nothing),
deverá retornar Nothing, pois não é uma computação válida. Caso o valor
do Maybe seja válido, mapeamo-lo e criamos uma nova estrutura Just f.
Dentre os conceitos de funtores, entende-se que os valores se envolvem em contextos
que vão além do valor, condicionados a comportamentos. No âmbito dos funtores
aplicativos, não somente os valores se envolvem em contextos e assumem comporta-
mentos. Neste último caso, as funções são envolvidas por um contexto mais complexo
que sua simples execução.
Mônadas
A linguagem de programação Haskell implementa, de forma algébrica, o
conceito de monoides, buscando satisfazer o princípio de identidade. Esse
princípio diz que sempre deve haver uma operação que permita que itens
possam ser unidos e que esta operação não tenha efeito. Para ser considerada
um monoide, é necessário que a operação não afete o resultado da função.
Por exemplo, a soma de dois números pode ser um monoide (1 + 0 = 1) ou um
array vazio ([]). Uma lista vazia concatenada a 1, 2 e 3 é o mesmo que 1, 2 e 3;
7Programação funcional: functors, applicative functors e monads
portanto, ela não implica em efeitos colaterais na função, passando a ser um
monoide (OLIVEIRA, 2017).
O termo mônada também tem suas origens na teoria das categorias, re-
presentando, de forma matemática, a prática ou execução de computações
que apresentam efeitos colaterais, como a leitura de arquivos. Oliveira (2017)
esclarece que uma mônada é composta por um funtor e, pelo menos, duas
transformações naturais. A linguagem de programação Haskell possui diversas
funções prontas, que são consideradas mônadas por retornarem justamente o
conceito de transformação natural, no qual podemos elencar as funções Maybe,
Identity, IO, etc. A mônada Maybe, especificamente, é utilizada para
realizar computações que podem retornar falhas, como no caso de listas vazias.
Para tanto, ela conta com os construtores Just e Nothing, que realizam
a verificação dos parâmetros da função, retornando a sentença verdadeira.
Em Haskell, as mônadas são representadas pela typeclass Monad e podem
ser testadas pela importação do módulo Control.Monad. A implementação
de uma mônada está diretamente ligada ao correto uso da função return e
do operador bind, representado pelo símbolo >>=.
A analogia mais utilizada para tentar descrever uma mônada é a teoria
das “caixinhas”. Por exemplo, utiliza-se, primeiramente, a ilustração de um
número qualquer, como o número 2, e explica-se que, fora da “caixinha”, ele é
puramente 2, mas ao entrar na “caixinha”, o número pode ou não ser 2 e pode
ou não ser puramente 2, como pode ser 2 acompanhado de comportamentos
ou contextos.
Quando o número 2 assume um valor além do seu próprio, ou seja, todo
um conjunto de contextos que se encontram dentro da “caixinha”, dizemos
que ele é um valor monádico. Com isso, é fácil deduzir que a “caixinha”, isto
é, a estrutura que envolve ou encapsula o 2 e tudo que estiver nele contido, é
o que conhecemos como mônada.
Um mônada é toda e qualquer estrutura que possua dentro de si um compor-
tamento ou contexto que só pode ser acessado por meio de funtores específicos,
como o utilizado neste capítulo, o fmap. O resultado da aplicação do fmap
Maybe, por exemplo, é uma mônada, pois ele gerará uma nova “caixinha”,
com novos valores e comportamentos. A função return apenas produz um
resultado quando chamada (SNOYMAN, 2012).
Programação funcional: functors, applicative functors e monads8
Função return
Return também é tida como uma transformação natural, pois ela recebe um
valor e o coloca dentro de um contêiner. Uma analogia utilizada para entender
a função return é a do livro e da caixa, em que x possui o tipo livro e y o
tipo caixa. Sendo assim, o ato de colocar o livro dentro da caixa chama-se
return (OLIVEIRA, 2017).
Por exemplo:
Prelude > return 10 :: [int]
[10]
O uso da função return neste exemplo demonstra a inserção dentro de
um contêiner de valor 10. Seguindo a analogia anteriormente explicada, o 10
seria o livro que foi colocado dentro da caixa.
Operador Bind (>>=)
Esta função denota um dos principais operadores para se trabalhar com estru-
turas monádicas. Em suma, o bind receberá um valor monádico, isto é, um
valor extraído, e trabalhará com ele até retornar outra mônada do mesmo tipo.
Se você utilizar uma mônada Maybe Just, ela só poderá retornar outro Just.
Notação do
Devido a sua complexidade, em um primeiro momento, e como forma de
remeter ao estilo imperativo que o programador está mais acostumado, a
função ou notação do serve para realizar o mesmo que o operadormonádico
bind, só que de modo mais intuitivo. Esta expressão permite combinar várias
computações, a ser executadas de forma sequencial.
Por exemplo:
main :: IO ( )
main = do
putStrLn "Hello world"
putStrLn "Escrevendo mais de uma linha"
A função do permite realizar uma sequência de instruções de forma intui-
tiva, semelhante às linguagens às quais estamos mais acostumados.
9Programação funcional: functors, applicative functors e monads
Mônada para listas [ ]
Também é possível manipular listas utilizando mônadas. Enquanto uma fun-
ção como a map manipula outra função de modo que uma condição seja
satisfeita, a mônada para listas pega todos os valores extraídos e os coloca
em uma nova estrutura do mesmo tipo, que pode ser utilizada como entrada
para outras funções.
Um exemplo simples disso é uma soma utilizando mônadas.
Prelude Control.Monad> [5,6] >>= \x -> [x+1]
[6,7]
A expressão monádica recebe uma lista com os elementos 5 e 6 como
parâmetros e uma função que irá somar esses parâmetros a 1. Ao final, o
resultado será uma nova estrutura, com os novos valores.
Mônada IO
Essa mônada é considerada uma das principais estruturas monádicas exis-
tentes, pois é responsável por permitir a interação do usuário com a máquina.
IO significa Input e Output, ou seja, entrada e saída de dados no computador
(DUBOIS, 2019).
É em razão desta função que é possível termos o famoso Hello World
em Haskell, pois a mônada IO tem notação semelhante ao void de Java, que
recebe um parâmetro vazio que serve para declararmos funções sem retorno,
como é o caso da impressão de Hello World na tela.
Utilizando a interface de compilação do Haskell, como, por exemplo,
o GHCi, basta criar um arquivo e nomeá-lo como desejar, escrevendo sua
função main.
Consideremos um arquivo nomeado index.hs:
main :: IO ( )
main = do
putStrLn "Hello world"
Programação funcional: functors, applicative functors e monads10
A função putStrLn possui um tipo string, que recebe uma string e a
mostra na tela. Basta declarar a função main, que significa que seu programa
começa por ali, e o compilador GHCI realizará a busca e gerará o código
executável. Se você utiliza sistemas operacionais Unix, digite em seu terminal
o seguinte comando:
$ ghc index.hs -o index
Isso compilará seu programa e gerará um código executável. Em seguida,
basta executá-lo no terminal:
$ ./index
Você também poderá utilizar outras funções de entrada e de saída para
imprimir seus dados na tela. A linguagem Haskell possui, além da putStrLn,
a função print, que também imprime na tela. Como funções de entrada,
podemos mencionar as funções readLn e getLine.
Todos esses termos, demonstrados dessa forma, fazem-nos entender que
eles fazem parte do dia a dia de um desenvolvedor, muitas vezes sem o co-
nhecimento deste. A programação funcional traz uma riqueza conceitual e
de qualidade às linhas do projeto e, juntamente a outros paradigmas, insere o
profissional de forma qualitativa no mercado do desenvolvimento.
No site da Haskell é possível verificar tudo que você precisa para começar a utilizar
esta linguagem e suas funcionalidades, como as apresentadas neste capítulo. Acesse
o link a seguir e confira.
https://qrgo.page.link/N8UbR
11Programação funcional: functors, applicative functors e monads
ARAÚJO, S. L.; ACIÓLY, B. M. Introdução ao Haskell. Vitória da Conquista: Universidade
Estadual do Sudoeste da Bahia, 2008. 86 p.
CAPRIOTTI, P.; KAPOSI, A. Free Applicative Functors. In: WORKSHOP ON MATHEMATI-
CALLY STRUCTURED FUNCTIONAL PROGRAMMING, 5., 2014, Grenoble. Proceedings
[…]. Grenoble: ETAPS, 2014. Disponível em: https://arxiv.org/pdf/1403.0749v3. Acesso
em: 3 out. 2019.
CHURCH, A. The calculi of lambda conversion. Princeton: Princeton University Press; Lon-
don: H. Milford; Oxford University Press, 1941. 77 p. (Annals of Mathematical Studies, 6).
DU BOIS, A. R. Programação funcional com a Linguagem Haskell. Edinburgh: School of
Mathematical and Computer Sciences, Heriot-Watt University, 2008. 76 p. Disponível em:
http://www.inf.ufpr.br/andrey/ci062/ProgramacaoHaskell.pdf. Acesso em: 3 out. 2019.
OLIVEIRA, A. G. Haskell: uma introdução à programação funcional. São Paulo: Casa do
Código, 2017. 161 p.
PATERSON, R. Constructing Applicative Functors. In: International Conference, Mathe-
matics of Program Construction, 11., 2012, Madrid. Proceedings […]. Madrid: Facultad
de Informática de la Universidad Complutense de Madrid, 2012. Disponível em: http://
www.staff.city.ac.uk/~ross/papers/Constructors.html. Acesso em: 3 out. 2019.
SNOYMAN, M. Developing web applications with Haskell and Yesod. Sebastopol: O’Reilly,
2012. 298 p.
SPIVAK, D. I. Category theory for the sciences. Cambridge: MIT Press, 2014. 496 p.
Programação funcional: functors, applicative functors e monads12
DICA DO PROFESSOR
Alguns conceitos mais complexos estão inseridos no paradigma da programação funcional
avançada. Nomes como funtores e mônadas têm a sua origem na teoria matemática que está
presente em toda a funcionalidade desse paradigma.
Na Dica do Professor, você irá entender um pouco mais sobre o funcionamento do funtor
Maybe.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) A teoria das categorias é uma teoria matemática, cujos preceitos auxiliam a nortear a
computação funcional. Em suma, ela trata de forma abstrata os valores matemáticos
e a relação entre eles.
Avalie as expressões a seguir e marque a alternativa que os define conceitualmente.
0+10 == 10 + 0 == 10
[ ] ++ 1,2,3 == 1,2,3 ++ [ ] == [1,2,3]
A) Monoide.
B) Bind.
C) Funtor.
D) Funtor aplicativo.
E) Mônada.
2) Estruturas monádicas também têm a sua origem na teoria das categorias e utilizam
expressões algébricas para realizar computações que causam efeitos colaterais. Uma
mônada utilizada em determinada função irá gerar outra estrutura de mesmo tipo.
Sabendo disso, dada a função main, que recebe uma string IO, marque a alternativa
que implementa corretamente uma linha de código que recebe uma string e
retorna uma mônada IO:
main :: IO ( )
A) main = getLine -> putStrLn
B) main = getLine >> = putStrLn
C) main = bind >> = putStrLn
D) main = print >> = putStrLn
E) main = getLine >> = print
3) Funtores são propriedades capazes de mapear um valor encapsulado, acessando o
contêiner para que a função possa executar a sua instrução utilizando
um determinado valor.
Baseado nisso, marque a alternativa que corresponde à função responsável pelo
encapsulamento desses diferentes tipos de dados:
A) Print.
B) getLIne.
C) Pure.
D) IO ( ).
E) Fmap.
4) A função ou o operador bind (>>=) retorna a uma função, elemento ou valor
monádico. No entanto, a notação do permite facilitar o trabalho com mônadas de
forma mais intuitiva em relação às outras linguagens mais utilizadas.
Sabendo disso, assinale a alternativa que representa o correto uso da notação do na
linguagem Haskell:
A) main :: IO ( )
main = do
line <- getLine
putStrLn line
B) main :: IO ( )
main -> do
line <- getLine
putStrLn line
C) main :: IO ( )
main = do;
line <- getLine;
putStrLn line
main :: IO ( do ) D)
line <- getLine
putStrLn line
E) main :: IO ( )
main = do
do getLine
putStrLn line
5) A utilização de expressões algébricas, funtores e mônadas permite manipular os mais
diversos tipos de estruturas. Uma dessas estruturas são as listas em que os valores
extraídos a partir da execução de uma dada instrução geram uma nova estrutura de
mesmo tipo.
Sabendo disso, analise a função monádica e marque a alternativa que traz o correto
resultado dessa execução:
Prelude Control.Monad > [10,50,60,100] >>= \x -> [x*x +x]
A) [110, 2550, 3660, 10100]
B) [100, 2500, 3600, 10000]
C) [200, 500, 7200, 20000]
D) [20, 100, 120, 200]
E) [10, 50, 60, 100]
NA PRÁTICA
Funções infixas são notações que podem ser utilizadas como substitutas da notação de uma
funçãopor meio da utilização de prefixos. Conceitos como fmap e funtores aplicativos utilizam
funções infixas para representar o seu uso.
Este Na Prática demonstra a experiência de Melina, que teve a missão de auxiliar o colega de
outra equipe de desenvolvimento. Embora experiente, ela teve as suas primeiras experiências
utilizando Haskell, deparando-se com conceitos e funcionalidades importantes no âmbito de
programação funcional.
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Introdução à Programação Funcional em OCaml
Você conhece a linguagem OCaml?? Assim, como a linguagem Haskell, essa linguagem é
fortemente tipada e baseada no cálculo lambda e na teoria das categorias. Por esse motivo, o uso
de funtores é primordial no decorrer de um código OCaml. Confira no link a seguir um
apanhado muito instrutivo dessa linguagem.
Conteúdo interativo disponível na plataforma de ensino!
Programação funcional com a linguagem Haskell
O estudo denota essa importante e ascendente linguagem funcional. Nesse contexto, conceitos
estudados nesta Unidade de Aprendizagem são abordados e favorecem ainda mais o
aprendizado.
Conteúdo interativo disponível na plataforma de ensino!
CaTReS - Ferramenta de apoio à pesquisa e ensino em Teoria das Categorias
Este estudo apresenta uma ferramenta facilitadora do aprendizado de conceitos importantes
relacionados à Teoria das Categorias. Esses conceitos introduzem qualidade e versatilidade no
uso da programação funcional.
Conteúdo interativo disponível na plataforma de ensino!
Programação funcional: currying
APRESENTAÇÃO
Currying é uma técnica muito utilizada por linguagens de programação funcional para informar
parâmetros de forma parcial a uma função.
Essa técnica possibilita transformar uma função que originalmente receberia uma dupla com
múltiplos parâmetros em um encadeamento de funções que recebe um só parâmetro cada.
Linguagens funcionais contêm, em sua estrutura de controle básica, a função. Muitas vezes,
utilizar uma função com diversos parâmetros pode ser inviável; portanto, linguagens com
suporte a closures podem ser utilizadas para currying.
Nesta Unidade de Aprendizagem, você irá entender a técnica de currying e suas vantagens, além
de ver aplicações práticas.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Explicar como é a técnica de currying.•
Discutir as vantagens da técnica de currying.•
Aplicar a técnica de currying.•
DESAFIO
A técnica de currying é usada em situações nas quais é preciso informar mais de um parâmetro
para uma função, mas os parâmetros não estão todos disponíveis ao mesmo tempo; ou seja, os
parâmetros necessários para invocar a função estão apenas parcialmente disponíveis.
Acontece que, em alguns casos, a função está sendo invocada com apenas um parâmetro e o
resultado retornado é um erro. Para resolver essa situação, você decide reescrever a função
utilizando a técnica de currying.
Apresente o código e a explicação de sua função.
INFOGRÁFICO
Currying é uma maneira de construir funções que permite a aplicação parcial dos argumentos de
uma função. Isso significa que você pode passar todos os argumentos que uma função está
esperando e obter o resultado, ou passar um subconjunto desses argumentos e recuperar uma
função que está aguardando o restante dos argumentos. A técnica está relacionada a closures,
uma forma de implementar a ligação de escopo entre funções aninhadas.
No Infográfico a seguir, você vai entender um pouco mais sobre currying e sua relação com
closures e linguagens funcionais.
CONTEÚDO DO LIVRO
Na programação funcional, trabalhar com funções que recebam somente um parâmetro é
comum. Em muitos casos, apesar da necessidade de avaliação de mais argumentos, e pela
característica desse paradigma de programação, não é possível obter todos os argumentos no
mesmo momento.
Sendo assim, a aplicação de técnica de currying, em que funções tradicionalmente construídas
recebendo mais de um argumento são construídas a partir de um aninhamento de funções,
possibilita que os argumentos sejam enviados parcialmente e o resultado final seja obtido.
No capítulo Programação funcional: currying, da obra Paradigmas de programação, você vai
conhecer mais sobre a técnica de currying e suas vantagens, além de ver exemplos de sua
aplicação utilizando as linguagens Haskell e JavaScript.
Boa leitura.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação
funcional: currying
Objetivos de aprendizagem
Ao final deste texto, você será capaz de:
� Explicar a técnica de currying.
� Discutir as vantagens do currying.
� Aplicar o currying.
Introdução
O currying é uma técnica utilizada em programação funcional, que consiste
basicamente em transformar uma função originalmente com múltiplos
parâmetros em uma que aceite apenas um. Isso é possível em linguagens
que implementam closure, fazendo um encadeamento de funções, em
que uma retorna a outra a qual recebe outro parâmetro, e assim suces-
sivamente até que o resultado esperado seja alcançado.
Inventada independentemente, como uma homenagem ao matemá-
tico Haskell Curry — por isso a origem do nome —, tem sua importância
devido à motivação prática da frequente utilização de funções obtidas
por meio de apenas algum dos parâmetros. Algumas linguagens de
programação, como Haskell, ML e JavaScript, possuem suporte sintático
nativo à técnica de currying.
Neste capítulo, você conhecerá um pouco mais sobre o que é a
técnica de currying, suas vantagens e aplicabilidades em programação
funcional.
Definição da técnica currying
Currying é uma técnica de transformação de uma função originalmente com
múltiplos parâmetros em uma avaliação parcial dos argumentos. A nomencla-
tura é uma homenagem a Haskell Curry, que estudava o método (FLANAGAN,
2013).
Segundo Flanagan (2013, p. 140), “métodos podem definir múltiplas listas
de parâmetros. Quando um método é chamado com uma lista menor de parâ-
metros, então será retornada uma função que recebe a lista de parâmetros que
falta como argumentos”. Podemos dizer, então, que o processo de currying
consiste em quebrar funções de n parâmetros em n funções, onde cada uma
deve receber apenas um parâmetro e retornar outra função que espera os
parâmetros restantes — logo, uma função representada originalmente por:
int, int -> int
Ao aplicarmos a técnica de currying, essa função teria o seu tipo alterado,
passando a ser representada por:
int -> int -> int
Para facilitar o entendimento, vamos analisar a Figura 1, a seguir, que
mostra originalmente um código em JavaScript de uma função que recebe os
parâmetros x e y e retorna a soma de x e y.
Figura 1. Função originalmente escrita em JavaScript
sem a técnica de currying.
Fonte: Adaptada de Lima (2016).
var add = function (x,y) {
add(1, 2) //3
return x + y;
};
Programação funcional: currying2
Agora, passamos à análise da Figura 2, que mostra exatamente a mesma
função, com a aplicação da técnica de currying.
Figura 2. Função com aplicação da técnica
de currying.
Fonte: Adaptada de Lima (2016).
var add = function(x) {
add(1)(2); //3
return function(y) {
return x + y;
};
};
Ao realizarmos uma análise mais superficial, em um primeiro momento,
apenas parece que estamos adicionando mais dificuldade sem nenhum ganho
específico. Mas já temos um grande retorno, pois estamos transformando o
código em pequenas partes mais expressivas e com maior possibilidade de
reuso (FLANAGAN, 2013). Pense em uma aplicação que necessite verificar
duas variáveis e retornar as duas em ordem alfabética. Porém, apenas uma
delas é recebida, usando uma função normal — certamente o retorno seria
um erro, pois não seria possível a comparação.
Ao aplicar a técnica de currying, poderia ser retornada uma função que
espere que a segunda variável seja enviada e, somente após, ordenassee
realizasse o retorno com as variáveis em ordem alfabética.
3Programação funcional: currying
Tanto currying quanto a aplicação parcial são conceitos muito poderosos e que podem
facilitar muito suas tarefas no dia a dia, mesmo em linguagens que não são totalmente
funcionais. Todavia, a aplicação parcial é um pouco diferente do processo de currying,
mas também envolve a questão dos tipos de uma função.
Como pudemos percebemos, a técnica de currying tem suas vantagens e,
por isso, uma grande importância em linguagens de programação funcionais.
Na próxima seção, discutiremos e conheceremos um pouco mais sobre as
vantagens dessa aplicação (FLANAGAN, 2013).
Vantagens do currying
Para entendermos as vantagens da utilização do currying, faz-se necessário
conhecer e estar ciente do termo aridade, que representa o número de argu-
mentos usados por uma função. Uma função que aceita um único argumento
tem aridade de um; uma função que recebe três argumentos tem uma aridade
de três (OLIVEIRA, 2017).
Além do fato de facilitar o processo de leitura de código, o currying oferece
aos desenvolvedores mais controle sobre suas funções. Em resumo, você será
capaz de escrever um código mais descritivo que se parece com um idioma
simples e, também, de mais fácil reutilização. Além disso, o currying é útil
quando você usa funções complexas e deseja ocultar sua implementação.
As funções podem ser classificadas com base no número de entradas que
aceitam: como se a função binária recebesse duas entradas, enquanto uma
função unária, apenas uma única entrada. Segundo Oliveira (2017, p. 142),
“em Haskell, toda função recebe apenas uma entrada, ou seja, toda função
em Haskell pode ser considerada unária”. Então, não é possível implementar
uma função que aceite vários parâmetros? Isso é possível, utilizando currying.
Programação funcional: currying4
Podemos, também, ver o currying como uma especialização, uma maneira tradicional
de lidar com funções n-árias gerais, desde que as únicas que você possa definir sejam
unárias.
Para Ayala-Rincón e Moura (2014, p. 98):
No cálculo lambda (a partir do qual as linguagens de programação funcio-
nal derivam), existem apenas abstrações de uma variável (que se traduz em
funções unárias nas linguagens funcionais). Em relação ao cálculo lambda,
acho mais fácil provar coisas sobre esse formalismo, já que você não precisa
lidar com o caso de funções n-árias (uma vez que você pode representar
qualquer função n-ária com várias funções unárias através do currying).
Não podemos compor diretamente funções que usam vários parâmetros.
Como a composição da função é um dos principais conceitos da programação
funcional, usando a técnica currying, podemos compor funções que usam
vários parâmetros.
Em um exemplo prático, veja a utilização e a vantagem de currying.
O framework de JavaScript angular tem uma implementação de curry que
permite “definir” parâmetros na função original e, posteriormente, passar um
número infinito de parâmetros adicionais. O exemplo apresentado na Figura 3,
a seguir, é o mesmo que é usado na documentação do framework.
Figura 3. Exemplo do framework angular.
5Programação funcional: currying
Considerando que f tem três argumentos curry, podemos chamá-la
novamente sem ter que os repetir, poupando, assim, a referida repetição de
código e argumentos:
// alerta "1, 2, 3, c, d"
f('c', 'd');
Currying é, na prática, vantajoso com a reutilização de código. Na próxima
seção, você verá alguns exemplos de aplicação de currying com as linguagens
de programação Haskell e JavaScript.
Aplicação do currying
Nas seções anteriores, entendemos o que é o currying e as vantagens de sua
aplicação. Para ilustrar, veremos um exemplo de aplicação da técnica utilizando
Haskell (OLIVEIRA, 2017).
Sendo PLUS uma função que adiciona dois números, queremos, então,
adicionar os números X e Y. X como a entrada da função PLUS, que retor-
nará uma função chamada PLUS X. A função PLUS X pega um número e
adiciona X a ele.
Agora, a entrada para essa função será Y, e a saída final será X + Y.
A Figura 4, a seguir, ilustra a função PLUS em uma implementação normal
e em sua versão currying.
Figura 4. Função PLUS em versão normal e aplicando currying.
X
XY PLUS PLUS
PLUS X
X + Y
Y
X + Y
Programação funcional: currying6
Pelo uso da função em currying, podemos resolver muitos problemas
facilmente. Por exemplo, precisamos criar uma função que use uma lista e
outra função como entrada. Aplique essa função a cada elemento dessa lista
e retorne à nova lista. Segundo Oliveira (2017, p. 146), “em Haskell, isso pode
ser feito com muita facilidade usando a função currying embutida, chamada
map.Definition”:
map :: (a -> b) -> [a] -> [b]
map _ [ ] = [ ]
map f (x : xs) = f x : map f xs
Analisando o código em Haskell, temos que:
� a primeira linha é a inicialização da função;
� o símbolo :: significa que "é do tipo";
� [a] representa uma lista de elementos semelhantes, entidade escrita
após a última -> é sempre o tipo de retorno da função;
� uma função em Haskell sempre retorna apenas uma entidade;
� (a-> b) define uma função de a a b;
� [] indica lista vazia, e _ indica "qualquer coisa";
� a segunda linha mostra que, se uma lista vazia e qualquer função for
inserida, a saída será uma lista vazia;
� x: xs é usado para remover os elementos um a um da lista, x é o
primeiro elemento (cabeça) e xs é a lista restante (cauda) – : significa
concatenação;
� a terceira linha está pegando cada elemento da lista e aplicando a função
f neles e concatenando-o com a lista restante;
� map (+7) [1, 2, 3, 4, 5] deverá retornar a lista [8, 9,
10, 11, 12], onde +7 é a função.
Passamos, então, à análise de outro exemplo de aplicação de currying,
utilizando a linguagem JavaScript. Imaginemos uma função que cumprimente
alguém. Essa função simples de saudação recebe um nome e uma saudação
e registra a saudação com o nome no console:
var greet = function(greeting, name) {
console.log(greeting + ", " + name);
};
greet("Olá", "Usuário"); //"Olá, Usuário"
7Programação funcional: currying
Essa função requer que o nome e a saudação sejam passados como argumen-
tos para funcionar corretamente. Mas podemos reescrevê-la usando currying
aninhado simples, para que a função básica exija apenas uma saudação e retorne
outra função que leve o nome da pessoa a ser cumprimentada.
O código reescrito aplicando currying é:
var greetCurried = function(greeting) {
return function(name) {
console.log(greeting + ", " + name);
};
};
Essa modificação na maneira como escrevemos a função permite-nos criar
uma nova função para qualquer tipo de saudação e transmitir a ela o nome da
pessoa que queremos cumprimentar:
var greetHello = greetCurried("Olá");
greetHello("Usuário"); //"Olá, Usuário"
greetHello("Usuário Novo"); //"Olá, Usuário Novo"
Também podemos chamar a função ao currying original diretamente. Isso
é feito apenas passando cada um dos parâmetros em um conjunto separado
de parênteses, um após o outro:
greetCurried("Olá")("Usuário"); //"Olá, Usuário"
O interessante é que, agora que entendemos como modificar nossa função
tradicional para usar currying e lidar com argumentos, podemos fazer isso
com quantos argumentos quisermos:
var greetDeeplyCurried = function(cumprimento) {
return function(separador) {
return function(enfase) {
return function(nome) {
console.log(cumprimento + separador + nome + enfase);
};
};
};
};
Programação funcional: currying8
O currying é uma técnica incrivelmente útil para programação funcional.
Ele permite gerar uma biblioteca de funções pequenas e facilmente confi-
guradas, que se comportam de maneira consistente, são rápidas de usar e
podem ser entendidas ao ler seu código. A adição de currying à sua prática
de codificação incentivará o uso de funções parcialmente aplicadas em todo o
código, evitando muitas repetições em potencial e ajudando vocêa ter melhores
hábitos de nomeação e tratamento de argumentos de função.
Acesse o link a seguir e veja comentários sobre a técnica de currying na programação.
https://qrgo.page.link/nzFzF
AYALA-RINCÓN, M.; MOURA, F. L. C. Fundamentos da programação lógica e funcional: o
princípio de resolução e a teoria de reescrita. Brasília: Finatec; UnB, 2014. 232 p.
FLANAGAN, D. JavaScript: o guia definitivo. 6. ed. Porto Alegre: Bookman, 2013. 1080 p.
LIMA, M. Entendendo Programação Funcional em JavaScript de uma vez. [S. l.], 3 mar. 2016.
Medium: tableless. Disponível em: https://medium.com/tableless/entendendo-
-programa%C3%A7%C3%A3o-funcional-em-javascript-de-uma-vez-c676489be08b.
Acesso em: 24 out. 2019.
OLIVEIRA, A. G. Haskell: uma introdução à programação funcional. São Paulo: Casa do
Código, 2017. 161 p.
9Programação funcional: currying
DICA DO PROFESSOR
Currying é o processo de pegar uma função que aceita n argumentos e transformá-la em n
funções que aceitam, cada uma, um único argumento. A aplicação parcial é usada para criar
funções com alguns dos parâmetros "já preenchidos". É como aplicar uma função, mas apenas
para alguns dos parâmetros; ou seja, aplicar parcialmente uma função.
Ambos os conceitos parecem idênticos, confundindo até mesmo alguns profissionais; no
entanto, existem diferenças.
Nesta Dica do Professor, você vai ver alguns exemplos de aplicação parcial e currying para
facilitar o entendimento das diferenças entre esses conceitos.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) Currying permite quebrar uma função de aridade superior a 1 em uma cadeia de
funções de aridade 1. Nesse caso, se há uma função com três parâmetros, para
realizar um cálculo e não utilizar a técnica de currying, ao enviar somente dois
parâmetros na chamada da função, há como retorno:
A) retorno parcial somente com o processamento dos dois parâmetros enviados.
B) erro de retorno, pois a função necessita que sejam informados os três parâmetros.
C) não conseguirá invocar a função, pois esta exige o envio de três parâmetros.
D) no caso de função de cálculo, será obtido um erro no retorno.
E) podem ser enviados os dois parâmetros, desde que o terceiro não seja utilizado no cálculo.
2) Currying é uma técnica baseada no princípio de função matemática, criada por
Moses Schönfinkel e Gottlob Frege, difundida principalmente por linguagens de
programação funcional, permitindo aplicar parcialmente uma função a algum dos
argumentos da função, por se tratar de uma técnica de encadeamento de funções.
Sobre essa afirmativa, assinale a alternativa correta.
A) Moses Schönfinkel e Gottlob Frege não foram os criadores da técnica de currying.
B) A técnica de currying não tem sua grande utilização por linguagens funcionais.
C) Aplicar parcialmente uma função está relacionado a aplicação parcial e não a currying.
D) Currying não é uma técnica baseada no conceito matemático de função.
E) Currying não se trata de uma técnica de encadeamento de funções conforme descrito.
3) Closure é um conceito que tem relação com a técnica de currying e três cadeias de
escopo: seu próprio escopo; escopo externo, com acesso às variáveis da função
exterior; e escopo com acesso às variáveis globais. Assinale a alternativa correta
acerca do que são closures.
A) São uma função que tem acesso às variáveis do escopo-pai.
B) São uma variável que possibilita retornar variáveis globais.
C) São um recurso exclusivo de linguagens funcionais.
D) São um recurso que necessita de suporte a currying para funcionar.
E) São uma técnica de aplicação de função parcial.
4) Currying e aplicação parcial lidam com parâmetros de funções e podem aplicar
parcialmente seus argumentos. Por isso, é comum uma certa confusão sobre esses
conceitos. Assinale a alternativa correta acerca da diferença entre currying e
aplicação parcial.
A) Um currying, diferentemente da aplicação parcial, não vai continuar retornando funções
unárias.
B) É possível aplicar currying sobre uma função que não tenha um valor fixo de argumentos.
C) Na aplicação parcial, não é possível realizar a chamada de um método sem informar todos
os parâmetros.
D) Aplicação parcial é só uma forma de lidar com assincronismo em programação funcional
de forma sequencial.
E) As aplicações parciais não se importam com o número de argumentos.
5) A aplicação da técnica de currying tem algumas vantagens, além de sua aplicação
básica, que é permitir que uma função receba um único argumento e retorne outra
função que recebe o próximo até ter todos os argumentos necessários. Assinale a
alternativa correta acerca de outro exemplo de vantagem da utilização de currying.
A) Permitir aos desenvolvedores um maior nível de controle sobre as funções.
B) Possibilitar funções com um maior nível de desempenho na execução.
C) Possibilitar funções n-árias a partir de uma função sem encadeamento.
D) Praticar a programação funcional, pois toda linguagem de programação funcional usa.
E) Possibilitar sistemas de redes distribuídas por criar funções assíncronas.
NA PRÁTICA
Em muitos casos, aplicando currying em programação, é possível escrever funções menos
verbosas e obter reusabilidade de código, além de sua aplicação principal, que é criar uma
função de aridade 1 que retorne outra função, até receber todos os argumentos necessários.
Veja, a seguir, a aplicação de currying utilizando JavaScript e alguns exemplos de como
simplificar o código e possibilitar mais reusabilidade.
Conteúdo interativo disponível na plataforma de ensino!
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Currying: uma técnica interessante usada em programação funcional
Neste vídeo, acompanhe uma explicação sobre a técnica de currying utilizada em programação
funcional.
Conteúdo interativo disponível na plataforma de ensino!
JavaScript – Currying
Assista, neste vídeo, a mais uma explicação sobre a técnica de currying e exemplos de sua
utilização com JavaScript.
Conteúdo interativo disponível na plataforma de ensino!
Transparência referencial, currying e closures em Java
Veja os conceitos da programação funcional em Java (transparência referencial, currying e
closures) e como podem ajudar a criar softwares mais robustos na programação do dia a dia.
Conteúdo interativo disponível na plataforma de ensino!
Linguagens multiparadigma 1: F#,
JavaScript, Python
APRESENTAÇÃO
Linguagem de programação multiparadigma é aquela linguagem que tem suporte a mais de um
paradigma de programação. Tal linguagem tem como intuito fornecer uma plataforma ao
desenvolvedor de software, de modo que ele possa trabalhar com os vários estilos de
programação, misturando esses diferentes paradigmas com o objetivo de desenvolver a solução
mais adequada tanto da perspectiva da solução quanto da sua perspectiva da eficiência
computacional.
Nesta Unidade de Aprendizagem, você vai conhecer três das principais linguagens de
programação multiparadigmas disponíveis no mercado: a linguagem F#, JavaScript e Python,
identificando os principais conceitos e fundamentos de cada uma dessas linguagens.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Especificar os principais conceitos da linguagem F#.•
Descrever os fundamentos da linguagem JavaScript.•
Identificar a linguagem Python.•
DESAFIO
As linguagens de programação, independente do seu paradigma, têm como premissa básica
solucionar problemas, bem como automatizar procedimentos, porém cada paradigma tem os
seus pontos fortes, assim direcionando-os a uma área específica, como a sua especialidade. No
entanto, as linguagens de programação multiparadigmas podem abranger todas essas áreas sem
distinções.
Analisando as opções disponíveis e as características mencionadas, indique qual seria a opção
mais adequada para a solução em questão. Justifique, também, os motivosque o levaram a essa
resposta.
INFOGRÁFICO
As linguagens de programação multiparadigmas são assim chamadas uma vez que não são
engessadas em um único paradigma de programação, ou seja, têm suporte a diversos paradigmas
de programação, fornecendo, assim, recursos variados para um determinado desenvolvimento.
Desse modo, independentemente da linguagem de programação, é possível solucionar
praticamente qualquer problema com a solução desenvolvida no paradigma adequado a ela.
Neste Infográfico, você vai ver algumas das características presentes nas linguagens de
programação F#, JavaScript e Python.
CONTEÚDO DO LIVRO
Na atualidade, para que uma linguagem de programação se torne um sucesso, ela deve se propor
a algo muito além de um nicho específico, ou seja, necessita conter várias formas de solucionar
programas, uma vez que terá de lidar com problemas variados. Nesse sentido, existem as
linguagens multiparadigmas que proporcionam a possibilidade de mesclar a utilização dos
paradigmas, de modo a proporcionar uma ferramenta de desenvolvimento de software flexível
para a confecção de soluções de software.
No capitulo Linguagens multiparadigmas 1: F#, JavaScript, Python, da obra Paradigmas de
Programa, você vai conhecer as linguagens de programação F#, JavaScript e Python, analisando
e evidenciando os seus principais conceitos e fundamentos.
PARADIGMAS DE
PROGRAMAÇÃO
Diego Bittencourt de Oliveira
Linguagens
multiparadigma 1:
F#, JavaScript, Python
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Especificar os principais conceitos da linguagem F#.
� Descrever os fundamentos da linguagem JavaScript.
� Identificar a linguagem Python.
Introdução
Considerando as necessidades cada vez mais complexas da área da
programação, podemos afirmar que nenhum paradigma desta soluciona
todos os programas de forma computacionalmente eficiente. Neste
contexto, surgem as linguagens multiparadigma, de modo a disponi-
bilizar linguagens flexíveis para que o desenvolvedor de software possa
combinar tais paradigmas e obter uma solução computacional eficiente
para a resolução do problema que almeja solucionar.
Neste capítulo, você conhecerá as principais linguagens de programa-
ção multiparadigma disponíveis, verificando conceitos e funcionalidades
de F#, Python e JavaScript.
Linguagem F#
Sebesta (2018) cita que F# (lê-se “f sharp”) se caracteriza por ser uma lingua-
gem de programação multiparadigma suportada pela plataforma .NET. Esta
é classificada como multiparadigma em razão de suportar o desenvolvimento
por meio da programação funcional, imperativa e orientada a objetos. Foi, ini-
cialmente, desenvolvida em 2005 por Don Syme, na Microsoft Research, tendo
posteriormente migrado para a Microsoft Developer Division, quando passou
a ser distribuída como parte integrante do Visual Studio 2010, integrando-o
até as versões atuais.
A plataforma .NET desenvolveu e disponibilizou o .NET Framework por iniciativa da
Microsoft, sendo que seu intuito é ser uma plataforma única para desenvolvimento e
execução de sistemas e aplicações. Dessa forma, todo código gerado para .NET pode
ser executado em qualquer dispositivo que possua uma versão de seu framework. Para
obter mais informações sobre o .NET Framework e sobre a linguagem de programação
F#, dentre outras linguagens de programação, acesse o link a seguir.
https://qrgo.page.link/fE7nh
Segundo Schade (2017), F# pode ser considerada uma nova forma de pensar
em programação para a plataforma .NET, uma vez que é capaz de se integrar
a outras linguagens presentes na plataforma. Ou seja, é possível integrar um
sistema ou aplicativo desenvolvido em C# ou, até mesmo, em Visual Basic
(duas outras linguagens de programação presentes na plataforma .NET), e
utilizar a linguagem F# nestes projetos, visto que esta oferece a possibilidade
de resolver problemas de alta complexidade de forma fácil e legível, como o
paralelismo. Dessa forma, pode-se obter proveito de todas as bibliotecas de
códigos que o ecossistema da plataforma .NET possui, incluindo:
� sintaxe leve;
� imutável por padrão;
� inferência de tipos e generalização automática;
� funções de primeira classe;
� tipos de dados avançados;
� correspondência de padrões;
� programação assíncrona.
Linguagens multiparadigma 1: F#, JavaScript, Python2
Esta linguagem de programação não se restringe à criação de classes es-
pecializadas em cálculos. Por exemplo, F# pode ser utilizado em áreas como
programação paralela, assíncrona e tratamento de dados. Também pode ser
aplicado ao desenvolvimento de classes de apoio às regras de negócio presentes
no sistema ou aplicação, bem como em algoritmos de processamento dire-
cionados a jogos, web services, ou qualquer outra aplicação que necessite de
soluções com as características desta linguagem. Portanto, podemos encontrar
possibilidades de aplicação para F# em, praticamente, qualquer área.
Por sua vasta gama de aplicações, a linguagem F# pode ser empregada em
sistemas como o desenvolvimento Web, mobile e desktop, além de poder ser
utilizada em aplicações de data science e na criação de scripts. Muitas tarefas
são mais simples de desenvolver em F#, como a criação de tipos complexos,
comparação e igualdade, processamento de listas, modelagem de máquina
de estados, entre outros.
No intuito de facilitar a aprendizagem de linguagens de programação, independente
destas ser ou não multiparadigma, existem ferramentas disponíveis on-line. Basta
acessar uma página, inserir um código-fonte e realizar o teste deste, aferindo seu
correto funcionamento. No link a seguir, podemos verificar uma ferramenta como
esta, com suporte à execução de códigos F#.
https://qrgo.page.link/yDWaC
A linguagem de programação F# é, primariamente, funcional. Seu conceito
se assemelha à linguagem de programação ML, surgida em meados de 1970.
Ambas possuem programação imperativa, com o diferencial de que a linguagem
F# possui suporte ao paradigma de orientação a objetos.
3Linguagens multiparadigma 1: F#, JavaScript, Python
Um programa desenvolvido em F# envolve, principalmente, a definição de
tipos e de funções, que são de tipo inferido e generalizadas automaticamente.
Tal fato permite que seu enfoque permaneça na solução do problema, manipu-
lando seus dados ao invés de despender tempo com detalhes da programação.
Na Figura 1, podemos verificar o exemplo de um pequeno código escrito em
F#, no qual uma função chamada getGreeting é chamada para realizar
a impressão na tela de uma lista de nomes, chamada names, composta por
três nomes.
Figura 1. Exemplo de código escrito em F#.
Fonte: Adaptada de What is... (2018, documento on-line).
Uma característica marcante da linguagem F# é possuir uma avançada
inferência de tipos. Na maioria das aplicações desenvolvidas por esta lingua-
gem não será preciso realizar a anotação dos tipos empregados na solução em
questão, de forma explícita. Sendo assim, a linguagem F# utiliza a técnica de
generalização automática, para que a inferência dos tipos de variáveis utilizadas
na aplicação seja obtida pela verificação do conteúdo que está armazenado
nestas. Dessa forma, o compilador examina cada parâmetro e determina se
a função tem uma dependência no tipo específico deste parâmetro. Caso não
encontre um tipo, o tipo é inferido como genérico (SCHADE, 2017).
Linguagens multiparadigma 1: F#, JavaScript, Python4
A comunidade de desenvolvedores é importante para auxiliar no desenvolvimento
de uma linguagem de programação: caso necessite de ajuda para solucionar algum
problema com o qual tenha se deparado, uma comunidade ativa pode facilitar sua
resolução. A linguagem F#, atualmente de código aberto, é mantida pela F# Software
Foundation, cuja missão é promover, proteger e aprimorar esta linguagem de pro-
gramação, além de fornecer suporte e facilitar o crescimento de uma comunidade
diversificada e internacional de programadoresde F#. Para obter mais informações,
acesse o link a seguir.
https://fsharp.org/
Linguagem JavaScript
Segundo Miletto e Bertagnolli (2014), o JavaScript é de uma linguagem de
programação leve, interpretada e orientada a objetos. Possui funções de pri-
meira classe (quando é possível operar funções), sendo conhecida por ser uma
linguagem muito utilizada em páginas Web, mas, também, muito utilizada
em ambientes fora dos navegadores Web. É uma linguagem de programação
baseada em protótipos, multiparadigma e dinâmica, suportando os paradigmas
de orientação a objetos, imperativo e funcional.
A linguagem de programação JavaScript foi originalmente criada na empresa Netscape,
por Brendan Eich, em 1994. Esta linguagem foi integrada ao navegador Web desen-
volvido pela Netscape, chamado Netscape Navigator. Nesta ocasião, estabeleceu-se
a concorrência entre o navegador da Microsoft, o Internet Explorer, e o navegador da
Netscape. O navegador da Microsoft suportava linguagens de programação muito
similares ao JavaScript da Netscape, VBScript e JScript, observando que a linguagem
JScript foi desenvolvida por engenharia reversa. Em 1996, a Netscape disponibilizou
o JavaScript para que outros desenvolvedores de navegadores pudessem equipar
seus navegadores com o JavaScript. Posteriormente, a própria Microsoft adotou o
JavaScript em seu navegador.
5Linguagens multiparadigma 1: F#, JavaScript, Python
Atualmente, todos os navegadores Web modernos e populares possuem
suporte à linguagem JavaScript, com interpretadores integrados. O código-
-fonte criado em JavaScript, na maioria das aplicações, é embarcado em
páginas HTML, de modo a permitir que este seja interpretado e executado
para fornecer mais recursos e interatividade a estas aplicações.
Dessa forma, podemos observar que JavaScript roda no lado do cliente
(client side) da Web, podendo ser utilizado para projetar e programar o compor-
tamento de uma página Web, a partir da ocorrência de um evento. JavaScript
é uma linguagem com uma curva de aprendizado pequena, porém, isto não
diminui seus poderes, sendo amplamente aplicadas ao controle de comporta-
mento de páginas Web (MILETTO; BERTAGNOLLI, 2014).
Conforme mencionado, o principal uso de JavaScript é para o desenvolvi-
mento de funções embarcadas ou incluídas em páginas HTML e que realizam
interação com o modelo de objeto de documentos (DOM). Alguns exemplos
de uso corriqueiro de JavaScript são:
� realizar a abertura de janelas (dialog) com controle sobre a posição e
tamanho e atributos, além de controlar as ações presentes nestas janelas;
� possibilitar a validação de valores de um formulário, de modo a verificar
se estes dados se encontram relativamente íntegros, visando evitar o
tráfego entre o servidor e o cliente de dados não informados ou sem
filtros simples, que podem minimizar erros;
� possibilitar mudanças em imagens, à medida em que o mouse de um
computador se movimenta sobre estas, possibilitando a melhor visua-
lização dos detalhes da imagem por parte dos usuários;
� realizar processos autônomos, de modo a fornecer informações atua-
lizadas ao usuário, sem que este seja direcionado a uma nova página.
Na Figura 2, podemos observar um exemplo da funcionalidade descrita,
na qual processos embarcados na página HTML buscam informações como
atualizações, solicitações e novas mensagens no servidor, atualizando-as na
página do usuário para notificá-lo sem que este necessite atualizar sua página
para obter tais informações.
Linguagens multiparadigma 1: F#, JavaScript, Python6
Figura 2. Exemplo de funcionalidade do JavaScript.
Fonte: Saiba... (2015, documento on-line).
Miletto e Bertagnolli (2014) citam que, de maneira simples, podemos avaliar
JavaScript como uma linguagem de script dinâmica, que suporta a construção
de objetos baseada em protótipos. Sua sintaxe básica é intencionalmente similar
tanto às de Java quanto de C++, assim, o número de desenvolvedores aptos a
desenvolver aplicativos é amplificado, de modo que os requisitos necessários
para aprender a linguagem são menores. Várias estruturas da linguagem, como
if, for, while, switch e try catch, funcionam da mesma forma que
nas linguagens citadas.
JavaScript pode operar tanto como linguagem procedural quanto linguagem
orientada a objetos. Objetos são criados via programação em JavaScript, na
qual métodos e propriedades são anexados ou clonados a objetos vazios em
tempo de execução, ao contrário das definições sintáticas baseadas na criação
de classes normalmente encontradas em linguagens compiladas, como C++ e
Java. Assim que um objeto é construído, ele pode ser utilizado como um padrão
(ou protótipo) para que objetos similares sejam obtidos por ele (MILETTO;
BERTAGNOLLI, 2014).
7Linguagens multiparadigma 1: F#, JavaScript, Python
Dentro das capacidades dinâmicas da linguagem JavaScript, podemos
listar as seguintes características:
� construção de objetos em tempo de execução;
� listas variáveis de parâmetros;
� variáveis de funções;
� criação dinâmica de scripts (pela função eval);
� introspecção de objetos (pela estrutura for ... in);
� recuperação de código-fonte (programas escritos em JavaScript podem
descompilar funções de volta a seus textos originais).
Para facilitar o desenvolvimento rápido e robusto que o mercado almeja, possuímos,
na atualidade, diversos conjuntos de bibliotecas que disponibilizam funções, cujo
objetivo é auxiliar e facilitar o desenvolvimento de sistemas e aplicações para que
os desenvolvedores possam utilizar estas funções sem que haja necessidade de
desenvolvê-las, uma vez que funções usuais já estariam disponíveis nestes códigos.
Sendo assim, a curva de desenvolvimento de um aplicativo ou sistema seria menor.
Nos links a seguir, temos algumas das bibliotecas mais utilizadas de código JavaScript.
� Angular JS:
https://angularjs.org
� JQuery:
https://jquery.com
� VueJS:
https://vuejs.org
� ReactJS:
https://pt-br.reactjs.org
Linguagens multiparadigma 1: F#, JavaScript, Python8
Linguagem Python
Menezes (2019) evidencia que a linguagem de programação Python foi criada
no final dos anos 1980 por Guido Van Rossum, no Centro de Matemática e
Tecnologia da Informação (CWI), na Holanda. O Python foi concebido para
se tornar o sucessor da linguagem ABC, dotado de recursos para ser capaz
de trabalhar com exceções e interagir com o sistema operacional Amoeba.
Atualmente, a linguagem Python é mantida pela Python Software Foundation e
possui licença de código aberto, chamada Python Software Foundation License. É
compatível com a General Public License (GPL) a partir da versão 2.1.1. Acesse o link
a seguir para conhecer o site da Python Software Foundation, baixar a versão mais
recente de Python para seu sistema operacional e aprender tudo de que você precisa
para sair programando.
https://python.org/
No Brasil, temos uma comunidade atuante de desenvolvedores Python. Acesse seu
portal oficial no link a seguir.
http://pythonbrasil.com.br
Python é uma linguagem de programação multiparadigma, uma vez que
suporta os paradigmas de orientação a objetos, de programação imperativa
e, em menor escala, de programação funcional. Trata-se de uma linguagem
interpretada, ou seja, seus códigos-fonte são transformados em uma lingua-
gem intermediária (específica de cada linguagem), que será interpretada pela
máquina virtual da linguagem quando o programa for executado (MENEZES,
2019). Na Figura 3, temos uma ilustração da sequência de execução de um
código-fonte Python.
9Linguagens multiparadigma 1: F#, JavaScript, Python
Figura 3. Esquema de execução de um aplicativo em Python.
Python possui múltiplas características que a tornam uma linguagem tão
promissora, atraindo cada vez mais desenvolvedores. Sua popularidade se deve,
por exemplo, ao fato de ser uma linguagem com uma curva de aprendizado
muito pequena, porém poderosa para se trabalhar. Possui uma sintaxe limpa
e clara, assim como um conjunto de bibliotecasestáveis e bem-estruturadas.
Sua sintaxe é minimalista, ou seja, utiliza somente o texto necessário,
tornando o código escrito em vários exemplos, como um texto em lingua-
gem formal. Em decorrência desta simplicidade sintática e de sua excelente
estruturação de bibliotecas, a manutenção de códigos da linguagem Python,
independente do código-fonte ser desenvolvido por um desenvolvedor ou por
terceiros, é de fácil compreensão e fornece uma curva de entendimento muito
pequena (MENEZES, 2019).
Apesar de existir um tipo mais popular de implementação em Python, existem outras
implementações alternativas, que podem atrair o interesse de diferentes públicos.
� CPython — esta é a implementação original e mais mantida de Python, escrita
em C. Geralmente, os novos recursos da linguagem aparecem primeiramente
nesta implementação.
Linguagens multiparadigma 1: F#, JavaScript, Python10
� Jython — Python implementado em Java. Pode ser usada como linguagem de script
para aplicativos Java ou para criar aplicativos, utilizando as bibliotecas de classes
Java. Também é frequentemente utilizado para criar testes para bibliotecas Java.
� Python para .NET — esta implementação usa a implementação CPython, mas é
um aplicativo .NET, gerenciado e disponibilizado por bibliotecas .NET.
� PyPy — uma implementação do Python, escrita inteiramente em Python. Su-
porta vários recursos avançados, não encontrados em outras implementações,
como suporte sem pilha e compilador just-in-time. Um dos objetivos do projeto é
incentivar a experimentação com a própria linguagem, facilitando a modificação
do intérprete, uma vez que está escrita em Python.
Além das características já citadas, a linguagem Python é equipada com
uma tipagem dinâmica e forte, ou seja, o próprio intérprete de Python infere
o tipo de dados que uma variável recebe. Dessa forma, não há necessidade de
que o desenvolvedor da linguagem diga de que tipo determinada variável é.
Outra característica é a capacidade da linguagem Python operar em am-
bientes multiplataforma, sendo igualmente bem executado em plataformas:
� Windows;
� GNU Linux;
� UNIX;
� Mac/Apple.
Além das plataformas listadas, a linguagem ainda pode ser executada em
supercomputadores, além de smartphones. Pode ser utilizada, também, para
desenvolver pequenas aplicações e protótipos rápidos, mas possui bom suporte
para permitir o desenvolvimento de programas robustos. Além disso, vem
equipada com um conjunto de ferramentas para interface gráfica do usuário
(GUI), poderoso e fácil de usar, sendo compatível com as plataformas que
suportam a execução dos programas criados na linguagem.
11Linguagens multiparadigma 1: F#, JavaScript, Python
Existem diversas linguagens de programação disponíveis no mercado caracterizadas por
ser fortemente tipadas. Tomemos como exemplo a linguagem Python para explicar a
questão. Tipagem forte significa que o intérprete de Python realiza uma avaliação das
expressões (evaluate) e não realiza conversões automáticas entre tipos não compatíveis
(conversões de valores). Dessa forma, quando uma exceção chamada TypeError é
emitida, ou seja, ao fazer operações com tipos incompatíveis, a linguagem Python não
os converte automaticamente, emitindo as exceções mencionadas. Logo, o programa
irá falhar. Isto deve ser encarado de forma positiva, uma vez que o desenvolvedor
possuirá a certeza que o resultado é consistente.
De forma nativa, o Python disponibiliza acesso ao banco de dados SQLite,
mas para acessar os principais banco de dados, basta adicionar as bibliotecas
(drivers) de banco de dados com a qual se deseja interagir, para que, então,
seja possível negociar dados com determinada base.
O SQLite é uma biblioteca em linguagem C que implementa um mecanismo de banco
de dados SQL pequeno, rápido, independente, de alta confiabilidade e completo. O
SQLite é o mecanismo de banco de dados mais utilizado no mundo. Está embutido
em todos os telefones celulares e na maioria dos computadores, sendo fornecido em
inúmeras outras aplicações que as pessoas utilizam diariamente. Acesse o site oficial
do SQLite para obter mais informações sobre esta importante ferramenta.
https://sqlite.org
MENEZES, N. N. C. Introdução à programação com Python: algoritmos e lógica de pro-
gramação para iniciantes. 3. ed. São Paulo: Novatec, 2019. 328 p.
MILETTO, E. M.; BERTAGNOLLI, S. C. Desenvolvimento de software II: introdução ao de-
senvolvimento web com HTML, CSS, JavaScript e PHP. Porto Alegre: Bookman, 2014.
276 p. (Série Tekne; Eixo Informação e Comunicação).
Linguagens multiparadigma 1: F#, JavaScript, Python12
SAIBA como o Facebook determina os seus 9 melhores amigos. Portal do Litoral PB –
priorizando o Litoral Sul, [S. l.], 18 nov. 2015. Disponível em: http://www.portaldolitoralpb.
com.br/saiba-como-o-facebook-determina-os-seus-9-melhores-amigos/. Acesso em:
15 out. 2019.
SCHADE, G. Programação funcional em .NET: explore um novo universo. São Paulo:
Casa do Código, 2017. 323 p.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
WHAT IS F#. Microsoft Docs, Redmond, 2 Aug. 2018. Disponível em: https://docs.microsoft.
com/en-us/dotnet/fsharp/what-is-fsharp. Acesso em: 15 out. 2019.
13Linguagens multiparadigma 1: F#, JavaScript, Python
DICA DO PROFESSOR
A linguagem JavaScript, desenvolvida pela NetScape, tornou-se, hoje, praticamente uma
linguagem padrão em se tratando de scripts para fornecer recursos para páginas web. É evidente
que para adquirir o status de padrão, tal linguagem deve conter recursos que solidifiquem tal
status, de maneira a verdadeiramente fornecer funcionalidades que visam a enriquecer de
recursos onde ela é aplicada.
Nesta Dica do Professor, você verá mais informações sobre a linguagem JavaScript e as suas
aplicações.
Conteúdo interativo disponível na plataforma de ensino!
EXERCÍCIOS
1) As linguagens de programação multiparadgimas se caracterizam por terem suporte
ao desenvolvimento utilizando vários paradigmas de programação, como a
orientação a objetos, a programação imperativa e a programação funcional. O F#, ao
suportar tais paradigmas, dentre outros, caracteriza-se por ser uma linguagem de
programação multiparadigma.
Indique quais das opções a seguir representa uma característica da linguagem F#:
A) Sintaxe carregada.
B) Mutável por padrão.
C) Falta de integração.
D) Tipos de dados simples.
E) Programação assíncrona.
2) JavaScript é caracterizada por ser uma linguagem de programação multiparadigma,
ou seja, é capaz de proporcionar a programação utilizando diversos paradigmas de
forma simultânea em um mesmo conjunto de código. A cerca da linguagem
JavaScript, indique qual afirmação é correta:
A) Predominantemente compilada.
B) Proporciona maior fluxo server-side.
C) Sintaxe carregada.
D) Proporciona recursos como dialog.
E) Dificuldade de obter mão de obra.
3) Linguagem de programação multiparadigma que integra o Visual Studio desde a sua
versão 2010, sendo que com a sua utilização é possível desenvolver rotinas de alta
complexidade em códigos simples de fácil entendimento e possível de ser integrada a
outras linguagens de programação presentes na plataforma .NET.
Indique qual opção a seguir representa a linguagem de programação indicada:
A) JavaScript.
B) C++.
C) Python.
D) C#.
E) F#.
4) Linguagem de programação multiparadigma utilizada de forma predominante em
códigos que operam integrados em arquivos de código HTML, operando em client
side, de maneira a fornecer características como uma gama maior de funcionalidades,
propiciando interatividade à página.
Indique qual opção a seguir representa a linguagem de programação indicada.
A) JavaScript.
B) C++.
C) Python.
D) C#.
E) F#.
5) Python é uma linguagem multiparadigma utilizada em grande escala por muitos
desenvolvedores no mundo inteiro, destacando-se por ser uma linguagem open
source, ou seja, o seu código é aberto e disponívela qualquer pessoa para estudos, ou
qualquer outra atividade, desde que alinhada às suas licenças. A cerca dessa
linguagem, indique qual alternativa contém uma afirmativa correta:
A) Utilizada apenas para programação web.
B) Falta de suporte à herança.
C) Tem tipagem fraca e dinâmica.
D) Suporte único a tipos de dados mutáveis.
E) Tem tipagem dinâmica e forte.
NA PRÁTICA
Em diversas situações, os desenvolvedores de software podem se deparar com situações onde a
linguagem de programação de um software pode não ser adequada a determinadas aplicações,
sendo assim, outras linguagens podem vir a se tornar adequadas. Porém, a migração do sistema
para uma linguagem que suporta tais sistemas pode ser complexa devido à estrutura já existente.
Na Prática, você verá uma situação em que uma determinada aplicação necessita de recursos em
que a linguagem de programação atual não suporta.
Conteúdo interativo disponível na plataforma de ensino!
SAIBA +
Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do
professor:
Guia de F#
A linguagem de programação F# integra a plataforma .NET, sendo altamente integrável a outras
linguagens presentes na plataforma, de modo a proporcionar a criação de códigos que possam
ser mais legíveis e mais poderosos. No site da Microsoft, você poderá observar tais
características.
Conteúdo interativo disponível na plataforma de ensino!
JavaScript - O Guia Definitivo
JavaScript é uma linguagem fácil com uma curva de aprendizado muito pequena e, ao mesmo
tempo, muito poderosa, incorporando diversos recursos advindos de sua capacidade de ser
multiparadigma. No capítulo 1 deste livro, você pode encontrar essas e muitas outras
características.
Python para quem está começando
Conteúdo interativo disponível na plataforma de ensino!
Linguagens multiparadigma 2: F#,
JavaScript, Python
APRESENTAÇÃO
Na atualidade, novos desafios vêm sendo impostos às linguagens de programação. Esses
desafios visam que uma mesma linguagem de programação venha a comportar a criação de
soluções simples para problemas complexos que muitas vezes exigem paradigmas distintos para
a sua melhor resolução.
Nesse sentido, têm-se as linguagens de programação multiparadigma, que visam a possibilitar a
confecção de soluções promovendo a utilização de dois ou mais paradigmas de programação.
Nesta Unidade de Aprendizagem, você verá exemplos práticos de aplicação das três das
principais linguagens de programação multiparadigma disponíveis no mercado: F#, JavaScript e
Python.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Explicar a utilização da linguagem F#.•
Aplicar a linguagem JavaScript.•
Identificar o uso de Python.•
DESAFIO
O JavaScript é uma linguagem de programação amplamente utilizada em websites que atua em
cliente-side, sendo muito usada para esboçar o comportamento de uma página Web por meio da
ocorrência de um evento. Um evento pode ser o click de um mouse, a digitação um texto, entre
outras possibilidades. Dessa forma, é possível manipular a página conforme o comportamento
previsto para o evento em questão.
INFOGRÁFICO
As linguagens de programação apresentam algumas características que devem ser analisadas a
fundo, verificando-se seu comportamento diante das características indicadas, uma vez que,
dependendo da situação, podem confundir o desenvolvedor que está migrando de uma
linguagem de programação para outra.
Outra situação que deve ser verificada são as funcionalidades pré-existentes nas linguagens,
visando a evitar desperdício de tempo criando-se ou formatando-se algo de maneira
desnecessária.
No Infográfico, conheça algumas das características presentes nas linguagens de programação
F#, JavaScript e Python.
CONTEÚDO DO LIVRO
A possibilidade de mesclar o uso dos diversos paradigmas de programação aos quais
determinada linguagem de programação tem suporte proporciona a implementação de software
de maneira flexível.
Observando esse fato, para que uma linguagem de programação atinja boa popularidade entre os
desenvolvedores, ela deve apresentar diversos recursos, de modo a possibilitar a utilização em
conjunto dos paradigmas de programação a que ela tenha suporte.
No capítulo Linguagens multiparadigmas 2: F#, JavaScript, Python, da obra Paradigmas de
programação, conheça as linguagens de programação F#, JavaScript e Python, analisando suas
aplicações e exemplos.
Boa leitura.
Paradigmas de
programação
Diego Bittencourt de Oliveira
Linguagens
multiparadigma 2:
F#, JavaScript, Python
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Explicar a utilização da linguagem F#.
� Aplicar a linguagem JavaScript.
� Identificar o uso da linguagem Python.
Introdução
Observando a crescente necessidade de soluções computacionais cada
vez mais complexas, pode-se concluir que um paradigma de programa-
ção, por mais flexível que seja, não é capaz de fornecer recursos para
solucionar de forma eficiente todas as necessidades existentes. Dessa
forma, as linguagens de programação multiparadigma se tornam opções
ideais para se obter aplicações com paradigmas mesclados, porém como
resultado soluções eficientes tanto de forma computacional quanto do
ponto de vista da construção de uma solução simples e de fácil enten-
dimento bem como manutenção facilitada.
Neste capítulo, você conhecerá as principais linguagens de progra-
mação multiparadigma disponíveis, verificando aplicações e exemplos
das linguagens F#, JavaScript e Python.
Linguagem F#
F# se caracteriza por ser uma linguagem de programação multiparadigma, ou
seja, que possui suporte a múltiplos paradigmas disponíveis para a utilização,
tanto de forma separada quanto de forma integrada, de modo a flexibilizar o
desenvolvimento de aplicações. Um dos diversos paradigmas suportados por
F# é o paradigma imperativo, comum a diversas linguagens de programação,
sendo, em muitos casos, o primeiro paradigma de programação com o qual os
alunos entram em contato ao iniciar seus estudos (SEBESTA, 2018).
Trata-se de um paradigma baseado em instruções e comandos, portanto,
é o programador que informa como e o que um aplicativo, sistema ou rotina
irá realizar. É neste paradigma que surgiram os laços de repetição, estruturas
condicionais, atribuição de valor a variáveis e controle de estado. A maioria
dos profissionais que trabalha com desenvolvimento de software utiliza este
paradigma de programação em seu dia a dia, muitas vezes, sem se dar conta
disto. Instruções como if, while, switch e for são tipicamente encon-
tradas em linguagens de programação imperativas (SCHADE, 2017).
Na Figura 1 é possível observar um exemplo de código desenvolvido em
F# que utiliza o paradigma imperativo, no qual uma variável mutável chamada
x possui como valor 1, que é modificado para 3. Em seguida, um laço for
é executado de 1 a x, realizando a impressão de i. Após a execução deste
código, temos as informações impressas a seguir.
Conteúdo de i: 1
Conteúdo de i: 2
Conteúdo de i: 3
Ainda, em relação à Figura 1, pode-se observar a presença da declaração
mutable, que indica que o valor de x poderá ser modificado. Logo, trata-
-se de um dado mutável e, portanto, seu valor pode ser modificado. Caso a
declaração mutable não fosse utilizada ao executar o código da Figura 1,
teríamos um erro. Neste caso, seria indicado ao desenvolvedor que a declaração
let mutable x = expression deve ser considerada.
Linguagens multiparadigma 2: F#, JavaScript, Python2
Figura 1. Exemplo de código utilizando o paradigma imperativo escrito em F#.
Outro paradigma suportado pela linguagem F# é o paradigma funcio-
nal, que possui dois conceitos básicos para que este possa ser compreendido
(SCHADE, 2017):
� Funções puras: são funções que podem acessar apenas os valores
que receberam por argumentos e, como consequência, não podemter
nenhum efeito colateral.
� Imutabilidade: refere-se a objetos ou estruturas de dados que, uma vez
inicializados, não podem sofrer nenhuma mudança em seus valores.
Isso os proporciona uma maior facilidade de compreensão, assim como
fornece segurança para que sejam utilizados.
Na Figura 2, observa-se a existência de três funções puras que utilizam
dados imutáveis: a função soma, a função subtrai e a função impri-
mirTresNumeros. Ao executar o código em questão, temos o resultado
impresso a seguir.
Número 1: 5
Número 2: 17
Número 3: 12
3Linguagens multiparadigma 2: F#, JavaScript, Python
Neste exemplo, foram passadas as seguintes informações: numero1 com
o valor 5, numero2 com o resultado da função soma 10 7, que resulta no
valor 17, e o numero3 com o resultado da função subtrai 20 8, que
resulta no valor 12.
Figura 2. Exemplo de código utilizando o paradigma funcional escrito em F#.
Outro importante paradigma suportado pela linguagem F# é a orientação
a objetos, sendo este implementado por meio do recurso de tipos complexos
de dados. Na Figura 3 podemos observar como este conceito é implementado
nesta linguagem, em que temos a classe ClasseBase, que possui um atributo
mutável z, iniciado com o valor 0. Além disso, temos a especificação de um
método abstrato chamado funcao1, declarado como abstract member,
método que recebe como parâmetro um dado do tipo inteiro (int) e retorna
uma informação do mesmo tipo. Em seguida, temos a implementação do
método indicado, que recebe um valor por a, soma ao valor já existente de z
e armazena o resultado nesta implementação. Além disso, a função retorna z.
Linguagens multiparadigma 2: F#, JavaScript, Python4
Ainda, na Figura 3, temos um exemplo do conceito de herança desenvolvido
em F#, de modo que a ClasseBase é herdada por ClasseDerivada,
utilizando a declaração inherit, além de criar uma nova implementação
para o método funcao1, que nesta implementação apenas soma 1 ao valor
recebido em a.
Figura 3. Exemplo de código utilizando o paradigma de orientação a objetos escrito em F#.
Assim, observamos que F# possui fácil capacidade de implementação de
aplicativos. Nesta linguagem, podemos utilizar diversos paradigmas de pro-
gramação, o que facilita o desenvolvimento e diminui o trabalho manual do
desenvolvedor, de modo que os códigos desenvolvidos possuem uma sintaxe
leve, mas poderosa.
Linguagem JavaScript
Em virtude de JavaScript possuir uma sintaxe muito parecida (de forma pro-
posital) a outras linguagens de programação, visando uma maior facilidade
na disponibilidade de desenvolvedores dessa linguagem. Este fato levou Ja-
vaScript a possuir fortes características do paradigma imperativo, assim como
do paradigma de orientação a objetos (MILETTO; BERTAGNOLLI, 2014).
No Quadro 1 podemos observar os principais tipos de dados disponíveis para
utilização na linguagem de programação JavaScript.
5Linguagens multiparadigma 2: F#, JavaScript, Python
Fonte: Adaptado de JavaScript... (2019, documento on-line).
Variáveis Explicação Exemplo
String Uma sequência de texto
é conhecida como string.
Para mostrar que o valor
é uma string, você deve
colocá-lo entre aspas.
var myVariable =
'Bob';
Number Simplesmente, um
número. Números não
estão entre aspas.
var myVariable = 10;
Boolean Um valor verdadeiro ou falso.
As palavras true e
false são palavras
reservadas em JavaScript
e não estão entre aspas.
var myVariable = true;
Array Uma estrutura que permite
armazenar diversos valores
em uma única variável.
var myVariable =
[1,'Bob','Steve',10];
Acesse cada item do array
dessa maneira:
myVariable[0], myVa-
riable[1], etc.
Object Basicamente, qualquer
tipo de objeto. Tudo em
JavaScript é um objeto
e pode ser armazenado
em uma variável.
v a r m y V a r i a -
ble = document.
querySelector('h1');
Todos os exemplos acima
também.
Quadro 1. Tipos de dados presentes na linguagem de programação JavaScript
Linguagens multiparadigma 2: F#, JavaScript, Python6
O paradigma imperativo sofre forte influência da linguagem de progra-
mação C, que contém instruções como if, while, switch e for. Além
disso, o paradigma imperativo suporta operadores, sejam aritméticos ou
de comparação, comumente utilizados nas linguagens de programação.
Na Figura 4 temos um exemplo de programação imperativa na qual temos
uma variável input, sem definir um valor para esta. Dessa forma, ao ser
verificada no teste if, a função facaIsto será chamada (MILETTO;
BERTAGNOLLI, 2014).
Algumas características da linguagem JavaScript devem ser observadas ao utilizá-la
no desenvolvimento de aplicativos.
� A utilização do ponto e vírgula no final de uma linha de código indica em que ponto
uma instrução termina, porém, isto é necessário somente quando o desenvolvedor
precisa separar duas ou mais instruções em uma única linha. Alguns desenvolvedores
acreditam que utilização do ponto e vírgula no final de cada instrução é uma boa
prática de programação.
� A linguagem JavaScript é case sensitive, portanto, uma variável com o nome mi-
nhaVariavel é diferente de minhavariavel.
� Alguns nomes não podem ser utilizados para a criação de variáveis, pois estão re-
servados à linguagem JavaScript. Na imagem a seguir, veja quais são estas palavras.
7Linguagens multiparadigma 2: F#, JavaScript, Python
Figura 4. Exemplo de aplicação do JavaScript com o paradigma imperativo.
O paradigma de orientação a objetos também é predominante na linguagem
de programação JavaScript, sendo que esta possui vários objetos incluídos
em seu núcleo, como Math, Object, Array, e String (MILETTO; BER-
TAGNOLLI, 2014). O exemplo a seguir mostra como usar o objeto Math para
inserir no log um número aleatório, utilizando o método random().
console.log(Math.random());
É possível criar objetos personalizados com o JavaScript, como construtores,
propriedades (atributos de objetos) e métodos. Além disso, esta linguagem
suporta conceitos como herança, polimorfismo, encapsulamento e abstração.
Na Figura 5 temos um exemplo de criação de um objeto Pessoa, com um
atributo nome e um método dizerOla. Ainda, neste exemplo, temos a criação
de dois objetos do tipo pessoa, assim com o acesso ao atributo presente neste
e a chamada ao método implementado na classe.
Linguagens multiparadigma 2: F#, JavaScript, Python8
Figura 5. Exemplo de aplicação do JavaScript com o paradigma de orientação a objetos.
Em relação ao paradigma funcional, na linguagem JavaScript o conceito
de funções de alta ordem se destaca, sendo que este proporciona a capacidade
de uma função de receber como parâmetros ou argumentos tanto valores
quanto outras funções, e pode retornar também uma função ou valores sim-
ples (MILETTO; BERTAGNOLLI, 2014). Na Figura 6 temos um exemplo de
aplicação do paradigma funcional em que podemos observar a utilização de
funções de alta ordem. As funções sum e mult são passadas pelo parâmetro
da função calculate e, assim, estas são invocadas e executadas conforme
previsto, retornando a soma ou o produto como desejado no momento da
chamada à função.
9Linguagens multiparadigma 2: F#, JavaScript, Python
Figura 6. Exemplo de aplicação do JavaScript com o paradigma funcional.
Linguagem Python
A linguagem Python possui tipagem dinâmica, ou seja, não é necessário in-
formar o tipo de uma variável, apesar de os tipos existirem, sendo eles: inteiro
(int), ponto flutuante (float), booleano (bool), complexo (complex) e
string (str). Além disso, esta linguagem tem operadores que realizam suas
funcionalidades previstas sobre valores e variáveis, sendo (MENEZES, 2019):
� operadores aritméticos (+, -, *, /, %, **, +=, -+, *=, /=, %=, **=);
� operadores de comparação (>, <, ==, >=, <=, <>, !=, is, in);
� operadores lógicos (and, or, not);
� operadores de atribuição (=).
Linguagens multiparadigma 2: F#, JavaScript, Python10
O desenvolvedor Python deve estar atento às palavras reservadas na linguagem
Python, uma vez que sua utilização como