Prévia do material em texto
8ºAula
Introdução à Programação
Orientada a Objetos
Objetivos de aprendizagem
Ao término desta aula, vocês serão capazes de:
entender o conceito de programação orientado a objetos;
criar classes na linguagem C++;
declarar atributos encapsulados;
criar métodos;
criar objetos.
Olá, Caros(as) alunos(as),
Nesta aula, veremos uma introdução ao paradigma de
programação orientada a objetos, abordando o conceito de
classes, atributos e métodos. Veremos que a programação
orientada a objetos é um paradigma um pouco diferente da
programação estruturada.
Bons estudos!
175
Linguagem de programação II 50
1. Programação Orientada a Objetos
2. Conceitos Básicos
3. Implementação de OO
Nas aulas anteriores, estudamos conceitos de programação
estruturada na linguagem C++. Entretanto, a linguagem
C++ possui outros aspectos além dos tratados até agora. O
verdadeiro poder da linguagem C++ está na sua versatilidade e
capacidade de ser programada em diferentes paradigmas, seja na
programação estruturada ou na programação orientada.
Com o decorrer dos anos, os softwares desenvolvidos
tornaram se cada vez mais complexos, forçando a linguagem
de programação sofrer uma revolução para se adaptar. Em
meados dos anos 60 nasceu a programação estruturada
que estimulada por linguagens como C e Pascal. Usando-se
linguagens estruturadas, pela primeira vez, foi possível escrever
programas complexos de maneira fácil. No entanto, com a
programação estruturada surgiu outro problema, quando um
projeto atinge certo tamanho, ele torna-se incontrolável, pois
a sua complexidade excede a capacidade desse paradigma
(TREVELIN, 2007).
Ao longo do tempo, os métodos foram criados para tentar
permitir ao programador tratar problemas com complexidades
grandes. E a cada passo combinava os melhores elementos
dos métodos anteriores com mais avanços. Para resolver
esse problema, a programação orientada a objetos foi criada
(DEITEL, 2012).
A programação orientada a objetos aproveitou as
melhores ideias da programação estruturada e combinou-as
com novos conceitos poderosos para a arte da programação. A
programação orientada a objetos permite que um problema seja
mais facilmente decomposto em subgrupos relacionados. Então,
usando-se a linguagem, podem-se traduzir esses subgrupos em
unidades autocontidas chamadas objetos. Todas as linguagens
de programação orientadas a objetos possuem três coisas em
comum: objetos, polimorfismo e herança (DEITEL, 2012).
1.1 - Paradigmas de Programação
Paradigmas de programação são conjuntos de ideias que
fornecem uma visão sobre a estruturação e execução um projeto
de software. Pense num paradigma como uma maneira de se
resolver um problema, e para esse problema podemos escolher
entre variadas metodologias para resolvê-lo e ao desenvolver
um programa adotamos um paradigma de programação
(TREVELIN, 2007).
A programação estruturada geralmente é o primeiro
paradigma a ser estudado na programação e tem como objetivo
escrever programas que sigam uma lógica linear, ou seja, com
início, meio e fim. A grosso modo, um programa escrito dessa
forma começa com a declaração das variáveis que serão utilizadas,
seguindo para a execução de comandos, funções e tomadas de
decisão numa sequência linear, até que todas as linhas de código
tenham sido executadas. É a maneira mais simples de se escrever
Seções de estudo
1 - Programação Orientada a Objetos
um programa, principalmente, porque utilizamos essa mesma
lógica linear no dia a dia: faça tal tarefa, depois caso tal condição
seja verdadeira realize outra tarefa, e assim por diante. Porém,
quando precisamos escrever programas realmente grandes
ou realmente complexos, a programação estruturada torna-se
ineficiente (KLANDERM,1999).
2 - Conceitos Básicos
A unidade principal da programação orientada a objetos é
a Classe. Uma classe é uma representação de um objeto ou ideia
real em forma de código, nela o programador deve expressar
separadamente as características operacionais dos detalhes
concretos de sua implementação. Simplificando, definimos uma
Classe para representar algo: por exemplo, um relógio. Para o
usuário, não é importante como o relógio funciona, tanto na
vida real como na programação: é importante apenas que o
usuário possa interagir com o relógio, seja olhando as horas, seja
ajustando o alarme ou configurando o horário correto. As
engrenagens ou funções que fazem o relógio funcionar ficam
“escondidas” do usuário: é isso que queremos dizer com
“separar as características operacionais dos detalhes da
implementação” (AGUILAR, 2008).
Podemos dizer que uma classe é uma estrutura que contém
atributos (variáveis) e métodos (funções) com o objetivo de
representar uma ideia ou objeto. Ainda pensando no exemplo
do relógio, dentro desta classe teríamos variáveis (ou membros)
para as horas, minutos, segundos e também para armazenar
o horário do alarme, assim como funções para visualizar o
horário atual, ajustá-lo ou ajustar o alarme. Porém, o usuário
não precisa ter acesso a todas estas variáveis: eles só precisam
interagir com as características operacionais do relógio. Assim,
criamos funções-membro para fazer esta interação: uma função
para ver as horas, outra para ajustar o horário e outra para ajustar
o alarme. Dessa forma, simplificamos a utilização da classe e
também evitamos que o usuário acesse e altere dados que
possam atrapalhar o funcionamento do programa (DEITEL,
2012).
2.1 - Classes, objetos função membro
e dado membro
A programação objeto geralmente é ensinada através de
exemplo com objetos do mundo real, até mesmo porque ela
surgiu com esse propósito. Portanto, vamos começar fazendo
analogia a um veículo. Imagine que você queira dirigir um carro
e deseje andar cada vez mais rápido pisando no acelerador. Mas
se pararmos para pensar antes mesmo de pegarmos o carro para
dirigir, existe a necessidade de alguém projetar esse carro. Um
carro geralmente começa a ser projetado através de desenhos.
Nesses desenhos contêm características do veículo como
motorização, detalhes na carroceria, freios, airbags, mecanismos
de controle de velocidade, tipo de câmbio e muitos outros
detalhes. Portanto, há toda uma necessidade de se escrever e
projetar o carro antes que pudéssemos dirigir.
Podemos utilizar esse exemplo do carro para tentar
entender o conceito de orientação a objetos. Vamos começar
pelo conceito básico de programação, ao executarmos um
código na linguagem C++ necessitamos de um método main
e lá dentro efetuamos algumas rotinas que geram alguma
176
51
interação com um usuário externo. Portanto, podemos fazer
analogia ao acelerador do carro, nós não sabemos o que está
acontecendo ao pisar no acelerador, nós apenas esperamos um
resultado “ir mais rápido”.
A orientação a objeto se inicia na declaração de uma classe.
Ainda fazendo analogia ao carro, podemos dizer que uma classe
é como o desenho do projetista do carro, ou seja, na classe é
onde vamos declarar os atributos do carro como: cor, tipo,
motorização, quantidade de portas. Na orientação a objetos
a ideia principal é tentar passar para a classe características do
mundo real.
Uma classe é composta por atributos e métodos, onde os
atributos são conhecidos como dado membro, e métodos são
conhecidos como função membro.
2.2 - Objetos
No mundo real nós identificamos objetos como algo
que podem ser percebidos por nossos sentidos, todo objeto
tem propriedades específicas, como cor, tamanho, forma etc.
Geralmente objetos têm características e comportamentos
diferentes. Ao voltarmos ao exemplo carro, podemos dizer que
o carro não deixa de ser um objeto. Uma das abordagens da
programação orientada a objetos é tentar utilizar esse conceito
dentro do nosso código.
2.3 - Classes
Uma classe é um tipo definido por meio da programação.
Uma classe pode ser considerada um bloco de construção
fundamentais dos programas orientados a objetos. Booch defini
uma classe como um conjunto de objetosque dividem a mesma
estrutura (AGUILAR, 2008).
As classes podem ser consideradas as espinhas dorsais da
maioria dos programas. A programação orientada a objetos é
um modelo baseado em classes, sendo assim, a classe define o
comportamento e estado de um objeto (DEITEL, 2012).
Uma classe possui membros internos do tipo dado e
funções. O membro dado armazena o estado associado aos
objetos do tipo da classe e as funções executam operações.
(AGUILAR, 2008).
Para declararmos uma classe utilizamos a palavra reservada
class seguida do nome abre chaves, logo após temos o corpo da
classe e fecha chaves finaliza o bloco.
class nomeClasse{
//declaração de dados atributos
//declaração de funções metodos
};
Uma classe a princípio é muito parecida com a struct, ou
seja, ela é declarada fora da função main e a princípio pode
armazenar variáveis dentro dela. No entanto, uma variável
dentro de uma classe é sempre chamada de atributo, por
definição, atributos são os elementos que definem a estrutura
de uma classe. A diferença é que na classe temos controle total
sobre os atributos, enquanto na struct todos seus elementos
eram acessíveis a todas as funções e programas. Enquanto na
classe podemos definir quem terá acesso aos seus atributos. Isso
é possível por causa do encapsulamento.
2.4 - Encapsulamento
Na programação orientada a objetos encapsulamento
significa separar o código em partes, o mais isolado possível.
O conceito de encapsulamento é tentar tornar o código mais
flexível, fácil de modificar e possibilitar a criação de novas
implementações. Esse conceito de encapsulamento restringe
a visibilidade de atributos e métodos a outras partes do
programa e a outros usuários. Todo objeto tem uma interface,
que determina como os outros objetos podem interagir
com ele. Existem três tipos de definição para a utilização do
encapsulamento (AGUILAR, 2008):
public – quando um atributo ou método é encapsulado
com o termo public, significa que esses membros são todos
acessíveis qualquer função dentro ou fora do programa.
Isso se aplica a todos os membros declarados até o próximo
especificador de acesso ou o fim da classe (BUENO, 2002).
private – quando um atributo ou método é encapsulado
com o termo private, significa que esses membros são acessíveis
somente dentro de funções de membro e amigos da classe.
Isso se aplica a todos os membros declarados até o próximo
especificador de acesso ou o fim da classe. Ficando visível
somente para membros de dentro da classe (BUENO, 2002).
protected – quando um atributo ou método é encapsulado
com o termo protected define o acesso a membros da classe e
a classe filhas.
Agora vamos ver como é realizado essa declaração na
prática.
class Carro{
private:
string nome;
int ano ;
string cor;
public:
string marca;
};
No código apresentado podemos observar um bloco
de códigos marcados como privados através do modificador
private e um atributo marcado como público através do
marcador public. Com a declaração de membros realizado
no exemplo, o único atributo que pode receber um valor é a
marca, o restante nunca será acessível. Podemos verificar isso
na chamada da classe na main, na figura a seguir é apresentado
as opções da classe.
Figura 1 Atributos encapsulados da classe Carro
Fonte: Do Autor.
177
Linguagem de programação II 52
Na figura observamos que o único membro (atributo)
da classe que está com a cor verde (acessível) é a marca. Mas,
qual a vantagem de bloquear os atributos de uma classe. No
exemplo acima nunca vamos conseguir atribuir um nome, cor
e ano a esse veículo? A resposta para esta pergunta é sim,
pois na programação orientada a objetos existe o conceito de
métodos assessores que nos auxilia a manipular esses dados,
como veremos no próximo tópico.
2.5 - Métodos
Um método equivalente a uma função, sub-rotina ou
procedimento da programação estrutura, ou seja, qualquer
função que escreva dentro de uma classe é chamada de
método. Os métodos são ações ou procedimentos, que podem
interagir outros objetos ou parte do programa. A execução
dessas ações se dá através de mensagens, tendo como função
o envio de uma solicitação ao objeto para que seja efetuada
a rotina desejada. No código a seguir podemos observar a
utilização de método dentro da classe (DEITEL, 2012).
#include
using namespace std;
class Carro
{
private:
int km;
public:
void adicionaKM()
{
km++;
}
};
Podemos observar que a implementação de um método é
algo fácil. Um método pode ser com retorno ou sem retorno,
ou seja, assim como na função quando não queremos retornar
marcamos o método como void. E quando desejamos retornar
algum valor, expressão ou objeto, marcamos o método com
um tipo de retorno, como por exemplo: int, float, double.
#include
using namespace std;
class Carro
{
private:
int km;
public:
void adicionaKM()
{
km++;
}
int pegaKM()
{
return km;
}
};
Agora temos dois métodos um com retorno e outro sem
retorno, todos os dois públicos, podendo assim ser utilizados
a partir de qualquer função ou programa. Um método, assim
como uma função, pode utilizar parâmetros no seu escopo.
2.6 - Métodos assessores
Quando temos uma programação com seus atributos
sendo diretamente acessados, podemos dizer que ela não
oferece os benefícios do encapsulamento. Como foi dito, o
encapsulamento nos oferece a ideia de tornar o software mais
flexível oferecendo um controle de acesso aos membros da
classe.
Na programação orientada a objetos existe uma regra
bastante clara sobre essas classes públicas, devemos fornecer
sempre atributos privados e métodos assessores públicos.
Portanto, para nossa classe carro devemos adicionar nossos
métodos assessores conforme é apresentado no código a seguir.
using namespace std;
class Carro
{
private:
string nome;
int ano;
string cor;
int km;
string marca;
public:
string getNome();
int getAno();
string getMarca();
string getCor();
int getKm();
};
Por convenção, todo método assessor é definido como
get seguido do nome do atributo com o formato camelcase
(Maiusculo), desta forma a classe apresenta de forma mais
clara qual método retornará valor de um atributo. Neste
paradigma existem dois tipos de métodos assessores, os
getters, citados no exemplo anterior, padronizam a forma que
os métodos que representam os atributos devem seguir para
retorno de atributos, e os métodos setters, que oferecem um
padrão pra que seja passado um valor a um atributo. A seguir,
podemos ver como é feita a definição dos métodos setters.
class Carro
{
private:
string nome;
int ano;
string cor;
int km;
string marca;
public:
void setNome(string nome);
void setAno(int ano);
void setMarca(string marca);
void setcor(string cor);
void setKm();
178
53
};
Um método setter deve sempre ser do tipo void e
receber o atributo por parâmetro, a vantagem na utilização
desse padrão para atribuir dados a um membro da classe é
poder controlar que tipo de dados o usuário irá inserir dentro
atributo. Imagine o seguinte cenário, um sistema que controla
uma conta bancária, nele temos que garantir que o cliente
nunca saque um dinheiro que não possua. Ao utilizarmos
uma struct, por exemplo, nós não conseguimos bloquear o
acesso a um variável saldo de dentro do bloco. Desta forma, se
inserirmos qualquer valor que desejarmos, já que temos acesso
direto a variável. Na programação a objetos podemos criar
uma validação dentro dos métodos assessores. Ou seja, desta
forma podemos definir que tipos de dados devemos aceitar.
class Conta
{
private:
int agencia;
int conta;
double saldo;
double limite;
public:
void setSaldo(double saldo){
if(saldo >0)
this->saldo = saldo;
}
void setLimite(double lim){
if(saldo >0)
limite = lim;
}
double saque(int valor){
if(saldo+limite >valor){
return valor;
}
return 0;
}
};No exemplo citado acima, observamos uma classe que
tenta representar uma conta corrente de um banco, nesta
classe contém métodos assessores settters para limite e
saldo, dentro deles foram acrescentados validadores que não
aceitam passagem de valores menores que 0. Desta forma,
o atributo garante que nunca será possível atribuir um saldo
ou limite que contrarie a regra estipulada. Também foi criado
na classe um método com retorno chamado saque, método
esse que valida a possibilidade de saque, portanto nunca será
possível retirada de um valor que não possui na conta. Esse
tipo de recurso somente é possível por causa do conceito
de encapsulamento da programação orientada a Objetos. No
exemplo acima, temos uma palavra reservada chamada this, o
this é um recurso de programação que aponta para membros
locais, ou seja, no exemplo citado acima temos dois atributos
com os mesmos nomes, desta forma o compilador não
conseguirá identificar quem deve receber quem. Utilizamos
o this para informar ao compilador que a variável local
deve receber a variável que vem por parâmetro. O this só é
necessário quando necessitamos referenciar algo para facilitar
a vida do compilador, por exemplo, no método setLimite não
foi necessária sua utilização, já que a variável que veio por
parâmetro possuía o nome diferente do atributo local.
3 - Implementação de OO
Na linguagem C++ podemos utilizar a programação
orientada a objetos de três formas, a primeira é criar métodos
dentro do mesmo arquivo que contém a função main, o que
não é recomendado, até mesmo porque a ideia da programação
orientada a objetos é a reutilização de código. A segunda é
criar um arquivo e implementar toda a classe dentro desse
arquivo, e a terceira é criar dois arquivos, sendo um do tipo
header que deverá conter somente a declaração da classe e
outro do tipo cpp que deverá conter a implementação dos
métodos. Inicialmente será apresentado o primeiro modelo
(não recomendado) para facilitar a explicação.
#include
using namespace std;
class Carro
{
private:
string nome;
string modelo;
int ano;
public:
string getNome()
{
return nome;
}
void setNome(string nome)
{
this->nome = nome;
}
string getModelo()
{
return modelo;
}
void setModelo(string modelo)
{
this->modelo = modelo;
}
int getAno()
{
return ano;
}
void setAno(int ano)
{
this->ano = ano;
}
};
int main()
{
Carro gol;
gol.setNome(“Gol”);
gol.setAno(2015);
gol.setModelo(“sport”);
return 0;
}
179
Linguagem de programação II 54
No código apresentado temos a declaração de uma
classe dentro do mesmo arquivo que contém a função main.
Por convenção, toda classe deve sempre ser iniciada com
letra maiúscula, e seus membros (atributos e métodos) iniciar
com letra minúscula. Na classe em cada método assessor é
utilizado o ponteiro this, por causa do nome do parâmetro
passado ao método set.
Dentro da função main temos um exemplo de declara e
utilizar nossa classe. Ao declarar uma classe, ela se torna um
objeto, ou seja, agora a variável criada a partir da classe é um
objeto. Podemos ter declarações de vários objetos do mesmo
tipo. Logo a seguir é apresentado o mesmo código, só que
agora utilizado da maneira recomendada.
#ifndef CARRO_H_
INCLUDED
INCLUDED
class Carro
{
private:
string nome;
string modelo;
int ano;
public:
string
getNome();
void
setNome(string
nome);
string
getModelo();
void
setModelo(string
modelo);
int getAno();
void setAno(int
ano);
};
#endif // CARRO_H_
INCLUDED
#include “Carro.h”
string Carro::getNome()
{
return nome;
}
void Carro::setNome(string
nome)
{
this->nome = nome;
}
string Carro::getModelo()
{
return modelo;
}
void Carro::setModelo(string
modelo)
{
this->modelo = modelo;
}
int Carro::getAno()
{
return ano;
}
void Carro::setAno(int ano)
{
this->ano = ano;
}
Fonte: Do Autor
Agora, uma classe utiliza dois arquivos, um com as
declarações e outro com a implementação, no entanto a
declaração do objeto dentro da função main continua igual ao
exemplo anterior. A única alteração no arquivo é a adição da
inclusão do arquivo Carro.h.
Retomando a aula
1 - Programação Orientada à Objetos
Apresentamos um conceito inicial ao paradigma de
programação orientada a objetos, destacando os motivos para
essa mudança.
2 - Conceitos Básicos
Estudamos os conceitos estruturais da criação de classes
que são a espinha dorsal da programação orientada a objetos,
vimos que as classes contêm o mapeamento de um objeto, ou
seja, onde é declarado seus atributos e métodos.
3 - Implementação de OO
Na seção 3, vimos como utilizar a programação orientada
a objetos em c++, ou seja, aqui vimos como é declarado uma
classe na linguagem c++, como encapsular atributos e como
implementar métodos.
Uma das características na programação orientada a
objetos em c++ é utilizarmos dois arquivos para criar uma
classe, no entanto é possível trabalhar com único arquivo,
assim como é feito pelo Java, por exemplo. Na aula, fizemos
uma breve introdução desse conceito, mais adiante no curso,
será apresentado todo o conceito desse poderoso paradigma.
DEITEL H.M DEITEL, P.J. C++: Como Programar.
Prentice-Hall, Inc., 5 a edition, 2012.
Vale a pena ler
Programação Orientada a Objetos com C++.
Disponível em: . Acesso em: 18 de ago. de
2018.
Programação Orientada a Objetos/Classes e
Objetos. Disponível em: . Acesso em: 18 de ago. de 2018.
Vale a pena acessar
Vale a pena
180
55
Classes, Objetos e Métodos. Disponível em: . Acesso em:
20 de ago. de 2018.
3 Dicas Simples de Como Pensar Orientado a Objetos.
Disponível em: . Acesso em: 20 de ago. de 2018.
Vale a pena assistir
Referências
AGUILAR, Luis Joyanes. Programação em C ++ - 2.ed.:
Algoritmos, estruturas de dados e objetos, MacGraw-Hill,2008
AMSA, Kris; SANTOS, Jeremias R. D. P. Aprendendo
C++. São Paulo: Makron Books do Brasil, 1999.
ARLEI, Adriano et all; A pré história da computação;
Departamento de Ciência da Computação Informática e
Sociedade; 2006.
BJARNE Stroustrup. A Linguagem de Programação C++.
Bookman, 2000.
BUENO, André Duarte; Apostila de Programação
Orientada a Objeto em C++; NÚCLEO DE PESQUISA EM
CONSTRUÇÃO; 2002.
CARVALHO, Flávia Pereira. Apostila de Programação
II- Linguagem de Programação C; Faculdade de Informática de
Taquara; 2008.
CARVALHO, Flávia Pereira. Linguagem de Programação C;
FIT - Faculdade de Informática de Taquara; 2008.
Carvalho, Herique. Programação Procedural Vs. Programação
Orientada a Objetos 2016.
DAMAS, Luis. Linguagem C completa e descomplicada. 10 ed.
LTC, 2006
DAVIS, Stephen R. Começando a programar em C++ para
leigos. Rio de Janeiro: Alta Books, 2015.
DEITEL H.M DEITEL, P.J. C++: Como Programar.
Prentice-Hall, Inc., 5 a edition, 2012.
DOUG BELL, Ian Morrey e John Pugh, “Software
Engineering: A Programming Approach”, segunda edição, Prentice
Hall, Nova Iorque, 1992.
ELLIS, Margaret A.; STROUSTRUP, Bjarne. C++,
Manual de Referência Comentado. Editora Campus, 1993.
GARCIA, André. Apostila de dev. Disponível em: . Acesso em: 28 de ago. 2018.
GCC «The C Preprocessor: Header Files» (em inglês).
GCC online documentation: The C Preprocessor. Disponível
em: Acesso em 19 de agosto de 2018.
HARRY FARRER. Programação estruturada de Computadores:
Algoritmos estruturados - [et. Al.] - 3° ed, [reimpr.] - Rio de
Janeiro: LTC, 2008.
JAMSA, Kris; KLANDERM LARS; SANTOS, Jeremias
René D. Pereira dos. Programando em C/C++:a bíblia. São
Paulo: Makron Books do Brasil, 1999.
LAUREANO, Marcos. Programando em C para Linux,
Unix e Windows / Marcos Laureano; Rio de Janeiro: Brasport;
2005.
NORTON, Peter; COSTA FILHO, Geraldo; AITKEN,
Peter. et al. A Bíblia do programador. Rio de Janeiro: Campus,
1994. J
PINTO, Rossano Pablo. Introdução à Arquitetura e
Linguagem Assembly de Processadores IA-32, Sistemas da Computação;
2007.
STANLEY B. LIPPMAN. C++ Primer. Addison-Wesley
Publishing Company, 1991. ISBN: 0-201-54848-8.
TREVELIN, Enrique Camargo. Apostila de C++;
UNIESP; 2007. FILHO, Cláudio Rogério Carvalho.
Operadores Lógicos Do C++; excript; 2015.
VICTORINE Viviane Mizrahi. Treinamento em Linguagem
C++. Prentice-Hall, Inc., 2 a edition, 2005.
VICTORINE Viviane Mizrahi; Treinamento em Linguagem
C++ (Módulos 1 e 2). Makron Books Editora Ltda. São
Paulo, 1994.
WALTER Savitch. C++ Absoluto. Addison-Wesley
Publishing Company, 2004. ISBN: 85-88639-09-2.
Minhas anotações
181