Implementação de Classe e Auto-Relacionamento em C++
1) Introdução
Um modelo de Diagrama de Classes representa a estrutura definida para o
armazenamento das informações dos elementos ou classes que irão trabalhar em
conjunto para solucionar um problema ou desafio. Sendo esse diagrama um modelo
conceitual, existe a necessidade de verificar a validade e completude desse modelo. Uma
das formas de se fazer isso é por meio de implementação, ou geração de códigos em
uma linguagem de programação Orientada a Objetos e realizações de testes de seu uso.
Neste material, será analisado um modelo de uma classe que possui um
relacionamento com ela mesmo. Quando isso ocorre, diz-se que há um Auto-
Relacionamento.
Como objeto de estudo, definine-se uma classe que representa o conceito
Disciplina. Considera-se, neste exemplo, que uma Disciplina possa possuir ou não como
pré-requisitos outras instâncias da Disciplina.
Ou seja, ela se relaciona com ela mesmo por meio do conceito “pré-requisito”. Por
exemplo, na Figura 1 a seguir, a disciplina EL65E possui como pré-requisito as disciplinas
EL64E, EL64F e EL64G. A disciplina EL64E, por sua vez, possui como pré-requisito a
disciplina FI64A.
Como essa estrutura poderia ser representada em um Modelo Orientado a
Objetos? Para responder a essa questão, este documento está divido em 5 Seções. Na
Segunda Seção, apresenta-se o cartão CRC da classe Disciplina. Na Seção 3, a partir do
cartão CRC, o modelo UML da classe é definido e apresentado. Nesse instante, destaca-
se que novas responsabilidades que não foram definidas no cartão CRC foram criadas
com a finalidade de orientar o programador de computador e também facilitar ou permitir o
(re)uso da classe. A Seção 4 apresenta a implementação da classe Disciplina. Encerrando
este documento, na Seção 5 um exercício é deixado para o aluno resolver.
De maneira similar ao descrito anteriormente, o programador de computador deve
ter a liberdade de definir ou personalizar a implementação. Ou seja, o programador de
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 1Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
computador implementa além dos métodos e atributos definidos no Diagrama de Classes
UML, novos métodos e atributos que ele/ela achar necessário.
Figura 1 - Grade parcial do Curso de Engenharia Industrial Elétrica da UTFPR, campus Curitiba adaptada para o exemplo investigado.
2)Representação Classe Disciplina O Cartão CRC apresentado na Figura 2, define os atributos ou “conhecimentos”
que um elemento da classe Disciplina deve possuir.
Figura 2 - CRC da Classe Disciplina
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 2Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
O cartão CRC representado na Figura 2 possui na área de Colaboradores, uma
própria instância da classe Disciplina. O Auto-Relacionamento ocorre quando é definido
como colaborador para uma classe, um exemplar da própria classe. Nesse caso, no canto
à direita do cartão CRC existe uma referência à própria classe do cartão, a classe
Disciplina. Isso acontece pois uma disciplina pode possuir nenhum, um ou vários pré-
requisitos e esse pré-requisito é uma outra instância da classe Disciplina.
3)Diagrama UML da Classe Disciplina A Figura 3, a seguir, apresenta o Diagrama de Classe da Classe Disciplina definida
no cartão CRC ilustrado na Figura 2. Alguns detalhes e considerações utilizadas nessa
representação merecem destaque, a saber:
• No diagrama UML, cada responsabilidade indicada no CRC, pode ser um atributo ou
um método.
• As responsabilidades Codigo, Nome, Quantidade de Aulas Teóricas, Quantidade de
Aulas Práticas e Quantidade de Aulas a Distância definidas no cartão CRC da Figura
2 foram representadas no diagrama da Figura 3.Os Anexos 6a), 6b), 6c) e 6d)
ilustram a associação entre as responsabilidades do cartão CRC e o Diagrama de
Classe.
• Cada atributo foi definido com o modificador de acesso private ou privado. Isso é
apenas uma recomendação: “atributos devem ser definidos com acesso private ou
protected”. Essa representação é indicada pelo sinal “-” que precede o atributo.
• Para cada atributo, métodos de acesso “geters” e “seters” de visibilidade pública
foram definidos. Por exemplo, os métodos públicos “+setNome(v: String) : void” e
“+getNome() : String” estão associados ao atributo Nome.
• A responsabilidade “pre-requisito”, por sua vez não foi representada de maneira
explícita no diagrama. De acordo com o diagrama, esse auto-relacionamento possui
a multiplicidade “0..*”. Essa multiplicidade significa que a quantidade de pré-
requisitos pode variar de instância de classe para instância de classe. O Anexo 6e)
ilustra a associação entre a representação do Auto-Relacionamento do Diagrama
UML e o cartão CRC.
• Cada linguagem de programação fornece ao programador um conjunto de opções
para representar o AUto-Relacionamento. Por exemplo, na linguagem C++, poder-
se-ia representar, por exemplo, com listas, vetores ou arrays esse conjunto de
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 3Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
elementos. Por outro lado, na linguagem Java, outras opções também estão
disponíveis. Para deixar o programador livre para definir qual será a forma de
implementação desse grupo de elementos, optou-se apenas por definir um método
de inclusão e outro de remoção de pré-requisito. Os métodos são
“addPreRequesitoNecessario(Disciplina)” e “removePreRequisitoNecessario
(Disciplina)”.
• As duas últimas responsabilidades definidas no cartão CRC “lista de quem sou pré-
requisito” e “lista pré-requisitos necessários” foram definidas como dois métodos no
diagrama de classes. Esses métodos são: listaPreRequisitosNecessarios() e
listaDeQuemSouPreRequisito().
• Três outros métodos foram definidos no diagrama de classes e que não foram
previstos no cartão CRC. Esses métodos são: i) “print( )”, ii) “equals(Disciplina)” e iii)
“clone( )”. O método “print( )” imprime as informações consideradas importantes do
conceito Disciplina. Por sua vez, o método “equals(Disciplina)”, verifica se duas
instâncias da classe disciplina podem ser consideradas iguais. O método “clone( )”
fornece uma cópia da instância.
• Dois construtores também foram definidos. Um deles, não recebe argumento algum
e o outro, recebe o código da disciplina e o seu respectivo nome.
• O Auto-Relacionamento denominado por “preRequisito” é representado por uma
linha que inicia e termina na própria classe. A multiplicidade desse relacionamento é
“0..*”. Essa multiplicidade informa que uma determinada instância da classe
Disciplina pode possuir nenhum, um pré-requisito ou vários.
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 4Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
Figura 3 - UML - Diagrama de Classe da Classe Disciplina
4.Implementação em C++
A definição da assinatura da classe é apresentada no arquivo Disciplina.h a seguir.
Algumas decisões realizadas necessitam ser exclarecidas, a saber:
• os atributos Nome e Codigo da Figura 3 foram definidos como elementos std::string.
• o Auto-Relacionamento é representado por elementos Vector. Nesse exemplo definiu-se
dois vetores ou vectors para armazenar as disciplinas que são pre-requisitos e também
de quais disciplinas a classe é pre-requisito.
• os métodos que irão fazer modificação nas instâncias de classes passadas como
parâmetros tiveram seus parâmetros definidos como ponteiros. Por exemplo: void addPreRequisitoNecessario(Disciplina *v);
• Alguns métodos que não foram definidos no Diagrama de Classes da Figura 3 foram
definidos durante a programação. Esses métodos são:
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 5Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
• vector<Disciplina> getPreRequisitos(); > definida com a finalidade de
mostrar como um método pode ter uma instância da classe vector de retorno.
• bool tenhoPreRequisitoNecessario(Disciplina v); > definido apenas
como método auxiliar para os outros métodos. Por não ter sido definido no Diagrama
de Classes, poderia ter sua visibilidade privada.
• bool souPreRequisito(Disciplina v); > definido apenas como método
auxiliar para os outros métodos. Por não ter sido definido no Diagrama de Classes,
poderia ter sua visibilidade privada.
4.1 Arquivo Disciplina.h
#include <string>
#include <vector>
using namespace std;
#pragma once
! class Disciplina {
! private:
! ! std::string Codigo;
! ! std::string Nome;
! ! int QuantidadeAulasTeoricas;
! ! int QuantidadeDeAulasPraticas;
! ! int QuantidadeDeAulasDistancia;
vector<Disciplina> preRequisitoNecessarios;
vector<Disciplina> deQuemSoupreRequisito;
! public:
! ! Disciplina(std::string v_codigo,std::string v_nome);
! ! Disciplina();
! ! void setQuantidadeAulasTeoricas(int v);
! ! void setQuantidadeAulasPraticas(int v);
! ! void setQuantidadeAulasDistancia(int v);
! ! int getQuantidadeAulasTeoricas();
! ! int getQuantidadeAulasPraticas();
! ! int getQuantidadeAulasDistancia();
! ! void setNome(std::string v);
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 6Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
! ! std::string getNome();
! ! void setCodigo(std::string v);
! ! std::string getCodigo();
void addPreRequisitoNecessario(Disciplina *v);
! void removePreRequisitoNecessario(Disciplina *v);
!vector<Disciplina> getPreRequisitos();
!bool tenhoPreRequisitoNecessario(Disciplina v);
!bool souPreRequisito(Disciplina v);
!void listaPreRequisitosNecessarios();
!void listaDeQuemSouPreRequisito();
!bool equals(Disciplina v);
!void print();
!Disciplina clone();
! };
// fim do arquivo h.
4.2 O Arquivo Disciplina.cpp
#include "Disciplina.h"#include <iostream>#include <ctype.h>
void Disciplina::print() { std::cout << endl; for (int i = 0; i < 70; i++) std::cout << "="; std::cout <<endl;
std::cout << "Disciplina Codigo: "! << Disciplina::Codigo << std::endl << "Disciplina Nome: " << Disciplina::Nome << std::endl << "Disciplina Quantidade de Aulas Teoricas: " << Disciplina::QuantidadeAulasTeoricas << std::endl << "Disciplina Quantidade de Aulas Praticas: " << Disciplina::QuantidadeDeAulasPraticas << std::endl << "Disciplina Quantidade de Aulas a Distancia: " << Disciplina::QuantidadeDeAulasDistancia << std::endl << "Total das aulas: " << (Disciplina::QuantidadeAulasTeoricas + Disciplina::QuantidadeDeAulasDistancia + Disciplina::QuantidadeDeAulasPraticas) << std::endl ; Disciplina::listaPreRequisitosNecessarios(); Disciplina::listaDeQuemSouPreRequisito();}void Disciplina::listaPreRequisitosNecessarios(){ // lista dos pre-requisitos std::cout << "Quantidade de Pre-Requisitos Necessarios: " << Disciplina::preRequisitoNecessarios.size() << std::endl; if (Disciplina::preRequisitoNecessarios.size() > 0)
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 7Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
{ vector<Disciplina>::const_iterator i; for(i=Disciplina::preRequisitoNecessarios.begin() ; i!=Disciplina::preRequisitoNecessarios.end(); i++) { cout << "\t Codigo : " << (*i).Codigo << " \t Nome : " << (*i).Nome << std::endl; } }}void Disciplina::listaDeQuemSouPreRequisito(){ std::cout << "Quantidade de Disciplinas em que sou Pre-Requisito: " << Disciplina::deQuemSoupreRequisito.size() << std::endl; if (Disciplina::deQuemSoupreRequisito.size() > 0) { vector<Disciplina>::const_iterator i; for(i=Disciplina::deQuemSoupreRequisito.begin() ; i!=Disciplina::deQuemSoupreRequisito.end(); i++) { cout << "\t Codigo : " << (*i).Codigo << " \t Nome : " << (*i).Nome << std::endl; } }}
Disciplina::Disciplina(std::string v_codigo, std::string v_nome) {! setNome(v_nome); Disciplina::Codigo = v_codigo; Disciplina::QuantidadeAulasTeoricas=0; Disciplina::QuantidadeDeAulasDistancia=0; Disciplina::QuantidadeDeAulasPraticas=0;}
Disciplina::Disciplina() { Disciplina::QuantidadeAulasTeoricas=0; Disciplina::QuantidadeDeAulasDistancia=0; Disciplina::QuantidadeDeAulasPraticas=0;}
void Disciplina::setQuantidadeAulasTeoricas(int v) {! if ( v >= 0 ) Disciplina::QuantidadeAulasTeoricas = v;}
void Disciplina::setQuantidadeAulasPraticas(int v) {! if (v >=0 ) Disciplina::QuantidadeDeAulasPraticas = v;}
void Disciplina::setQuantidadeAulasDistancia(int v) {! if (v >= 0 ) Disciplina::QuantidadeDeAulasDistancia = v;}
int Disciplina::getQuantidadeAulasTeoricas() {return Disciplina::QuantidadeAulasTeoricas;}
int Disciplina::getQuantidadeAulasPraticas() {
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 8Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
return Disciplina::QuantidadeDeAulasPraticas;}
int Disciplina::getQuantidadeAulasDistancia() {! return Disciplina::QuantidadeDeAulasDistancia;}
void Disciplina::setNome(std::string v) { std::string aux = v; for (int i = 0; i < v.length() ; i++) aux[i] = toupper(v[i]); Disciplina::Nome = aux;}
std::string Disciplina::getNome() {! return Disciplina::Nome;}
void Disciplina::setCodigo(std::string v) {! Disciplina::Codigo = v;}
std::string Disciplina::getCodigo() {! return Disciplina::Codigo;}
void Disciplina::addPreRequisitoNecessario(Disciplina *v){
if (Disciplina::tenhoPreRequisitoNecessario(*v) == false) { Disciplina::preRequisitoNecessarios.push_back(*v); v->deQuemSoupreRequisito.push_back(*this); }}
void Disciplina::removePreRequisitoNecessario(Disciplina * v){ int j=0; vector<Disciplina>::const_iterator i; for(i=Disciplina::preRequisitoNecessarios.begin() ; i!=Disciplina::preRequisitoNecessarios.end(); i++) { if ( v->Codigo.compare(Disciplina(*i).Codigo) == 0 ) { Disciplina::preRequisitoNecessarios.erase (Disciplina::preRequisitoNecessarios.begin()+j); vector<Disciplina>::const_iterator k; int m=0; for (k = v->deQuemSoupreRequisito.begin() ; k != v->deQuemSoupreRequisito.end(); k++) { if (this->equals(Disciplina(*k))) {v->deQuemSoupreRequisito.erase(v->deQuemSoupreRequisito.begin()+m); break; } m++; } break;
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 9Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
} j++; }}
bool Disciplina::equals(Disciplina v){ bool saida = false; if (Codigo.compare(v.Codigo) ==0 ) {if (Nome.compare(v.Nome) == 0 ) if (QuantidadeAulasTeoricas == v.QuantidadeAulasTeoricas) if (v.QuantidadeDeAulasDistancia== QuantidadeDeAulasDistancia) if (v.QuantidadeDeAulasPraticas == QuantidadeDeAulasPraticas) saida =true; } return saida;}
bool Disciplina::tenhoPreRequisitoNecessario(Disciplina v){ bool saida = false; vector<Disciplina>::const_iterator i; for(i=Disciplina::preRequisitoNecessarios.begin() ; i!=Disciplina::preRequisitoNecessarios.end(); i++) { if ( v.equals(Disciplina(*i))) {saida = true; break;} } return saida;}
vector<Disciplina> Disciplina::getPreRequisitos(){ return Disciplina::preRequisitoNecessarios;}
bool Disciplina::souPreRequisito(Disciplina v){ bool saida = false; vector<Disciplina>::const_iterator i; for(i=Disciplina::deQuemSoupreRequisito.begin() ; i!=Disciplina::deQuemSoupreRequisito.end(); i++) { if ( v.equals(Disciplina(*i)) ) {saida = true; break;} } return saida;}
Disciplina Disciplina::clone(){ Disciplina *saida = new Disciplina(); saida->Codigo = Codigo; saida->Nome = Nome; saida->QuantidadeAulasTeoricas = QuantidadeAulasTeoricas; saida->QuantidadeDeAulasDistancia = QuantidadeDeAulasDistancia; saida->QuantidadeDeAulasPraticas = QuantidadeDeAulasPraticas; saida->deQuemSoupreRequisito = deQuemSoupreRequisito; saida->preRequisitoNecessarios = preRequisitoNecessarios; return *saida;}
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 10Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
// fim do arquivo cpp
4.3 O Arquivo de teste main.cpp
/*
* File: main.cpp
* Author: robinsonnoronha
*
* Created on February 9, 2013, 5:25 PM
*/
#include <iostream>
#include <cstdlib>
#include "Disciplina.h"
using namespace std;
int main(int argc, char** argv) {
Disciplina MA61B("MA61B", "Matematica 1");
MA61B.setQuantidadeAulasTeoricas(90);
Disciplina MA61A("MA61A","Calculo 1"); MA61A.setQuantidadeAulasTeoricas(90);
Disciplina MA62A("MA62A","Calculo 2"); MA62A.setQuantidadeAulasTeoricas(60);
Disciplina FI63A("FI63A","Fisica 3"); FI63A.setQuantidadeAulasTeoricas(45);
FI63A.setQuantidadeAulasPraticas(60);
FI63A.addPreRequisitoNecessario(&MA61B);
FI63A.addPreRequisitoNecessario(&MA61A);
Disciplina FI64A("FI64A","Fisica 4"); FI64A.setQuantidadeAulasTeoricas(60);
FI64A.addPreRequisitoNecessario(&FI63A);
// exemplo de recebimento de pre-requesitos.
cout << "\n Pre-requesitos da Disciplina FI63A:\n";
vector <Disciplina> l = FI63A.getPreRequisitos();
cout << "\n Quantidade de Pre-Requisitos:" << l.size() << endl;
vector<Disciplina>::const_iterator i;
for(i=l.begin()
; i!=l.end(); i++)
{
(Disciplina(*i).print());
}
// exemplo do uso do Clone()
cout << "\n Clone:" <<endl;
Disciplina cloneFI63A = FI63A.clone();
FI63A.print();
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 11Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
return 0;}
4.4 Resultado da Execução.
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 12Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
5. Exercício
a) Implementar e testar a classe Pessoa e o Auto-Relacionamento “casada_com”.
b) A Classe Pessoa do exercício 5 foi modificada. , para o Exercício 5b).
Além do Auto-relacionamento “cada_com” com multiplicidade “0..1”, um novo Auto-Relacionamento deve ser implementado. Esse novo Auto-Relacionamento é denominado “amizadeCom” e possui multiplicidade “0..*”.
Modificar a classe Pessoa implementada no exercício 5a) de tal forma que ela represente esse novo Diagrama de Classe.
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 13Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
6. Anexos
a)
b)
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 14Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------
c)
d)
e)
UTFPR – DAELN - Disciplina de Fundamentos de Programação II ( IF62C ). 15Prof. Robinson Vida Noronha Tema: Implementação de Classe e Auto-Relacionamentos em C++----------------------------------------------------------------------------------------------------------------------------------------------