Bom dia, pessoal.
Aqui quem fala é o professor Simão.
Estamos em Curitiba,
no dia 10 de julho de 2020.
Estamos aqui pra falar do Grupo de Slides número 4.
Lista de Objetos.
Vou pôr em Modo Exibição.
Muito bem.
Antes de mais nada,
vamos fazer uma relembrança aqui.
Então, relembrando
qual tem sido o nosso
exemplo para estudos?
É um Sistema Acadêmico.
Aqui estão os requisitos
funcionais e gerais do Sistema Acadêmico.
Registrar no sistema um conjunto de Universidades.
Registrar no sistema um conjunto de Departamentos
relacionados a Universidades.
Registrar no sistema um conjunto de Disciplinas
relacionadas a Departamento.
Registrar um conjunto de Professores
relacionados a entidades pertinentes
como Departamentos e Disciplinas.
Registrar um conjunto de Alunos relacionados
a entidades pertinentes como Departamentos e Disciplinas
E pode ter mais requisitos.
Inclusive, nisso cabe a observação.
Esses requisitos funcionais e gerais
que serão expandidos e refinados, inclusive em termos técnicos,
nos enunciados dos exercícios.
Se dão assim porque estamos no âmbito de uma disciplina
aprendendo conceitos progressivamente.
Em um sistema real, naturalmente,
os requisitos deveriam ser definidos e estabelecidos
o quanto antes dentro de um ciclo de engenharia de software.
Conforme a gente já discutiu, tá,
isso é cada vez mais verdade quão mais crítico fica o sistema, tá.
Muito embora, deveria, do meu ponto de vista, ser verdade sempre.
Mas tudo bem.
Aqui tá a modelagem que a gente fez dos requisitos dados até então, né.
Você tem lá a classe Professor e classe Aluno derivado de Pessoa.
Você tem Professor associado com Universidade e Departamento.
Associações direcionais.
E você tem uma Universidade ali, agregando Departamento.
Aqui a gente fez aquela interpretação de agregação-fraca
pelo fato de usar um ponteiro, muito embora, a gente sabe que isso é uma interpretação.
Poderia tranquilamente ser agregação-forte
já que lá na análise é agregação-forte, né,
e a gente deve optar de ir pelo caminho de dizer: olha
se na Análise é uma agregação-forte,
no Projeto também vai ser, mesmo que eu implemente por ponteiro.
Isso aí já é assunto superado.
Aqui a gente passa pra um novo exercício,
no âmbito do nosso Sistema Acadêmico.
Baseando-se nos requisitos funcionais,
sejam gerais ou específicos,
pode-se derivar requisitos técnicos,
como estes abaixo que compõem o exercício 1A.
Crie uma classe Disciplina.
Associe cada Disciplina a um Departamento.
Cada Departamento deve ser capaz de armazenar uma lista de disciplinas.
Esta lista deverá ser simplesmente encadeada.
Muito bem.
Então vamos resolver o exercício, tá.
Associe cada Disciplina a um Departamento.
Muito bem.
Cada Departamento deve ser capaz de armazenar uma lista de disciplinas.
E, aqui, é o ponto principal
que a lista deverá ser simplesmente encadeada.
Aqui pela modelagem que a gente tá fazendo
sempre verificando se a gente tá cumprindo ou não os requisitos, tá,
mas o fato é que essa modelagem que a gente tá fazendo
a gente tá dizendo que o Departamento agrega um conjunto de uma ou mais Disciplinas,
Agrega-fortemente, ou seja, o Departamento vai ter as Disciplinas
o Departamento define as Disciplinas.
Se as Disciplinas pudessem pertencer a mais de um Departamento, daí,
não seria agregação-forte aqui na Análise seria agregação-fraca, bem entendido.
Aqui, a gente tá dizendo que a Disciplina só pode pertencer a um Departamento, tá.
Aqui, quando tem agregação forte, a cardinalidade é 1 por definição.
Nesse lado de cá.
Muito embora, a gente possa e até deva explicitar.
Então, agregação... o Departamento agrega-fortemente, se compõe
de uma ou mais Disciplinas
e cada Disciplina está agregada em um Departamento.
Aqui tem a modelagem dos elementos que tem em Departamento e
a modelagem do que tem em Disciplina, tá.
Isso do ponto de vista de Análise.
Aqui, a gente não tá contando ainda como vai ser
tratado esse conjunto de elementos de Disciplina, aqui, né.
Esse conjunto de... perdão, esse conjunto de Disciplinas
que vai estar dentro do Departamento, tá.
A gente tá só analisando que Departamento tem Disciplinas
do ponto de vista de mais alto nível.
Se a gente passar já pro Projeto,
você percebe que, aqui, eu resolvi
interpretar uma agregação-fraca porque eu vou usar ponteiros pra fazer essa agregação
de Departamento ter Disciplinas, tá,
mas, novamente, isso aqui é uma interpretação. É um viés que eu utilizei.
Poderia tranquilamente continuar usando agregação-forte
já que na Análise é forte
só íamos ter que ser coerentes com essa nova interpretação.
Legal. Aqui, o que é importante observar é o seguinte,
dá pra fazer comentário, ademais. Aqui é linha pontilhada, tá.
A impressão do slide que tá fazendo uma linha contínua mas ela é pontilhada.
Implementação via uma lista simplesmente encadeada
baseada em ponteiros pDisciplPrim e pDisciplAtual de Departamento
Tá ali, ó, pDisciplPrim e pDisciplAtual.
De fato são ponteiros de Disciplina.
E pProx de Disciplina.
Tá ali, ó, pProx de Disciplina.
Inclusive isso aqui o ponteiro aqui, ó, todos os ponteiros, na verdade, aqui estão públicos, tá.
Na versão de vocês, é um exercício,
vocês deixem esses ponteiros privados, tá.
Aqui eu pus pra em algum momento pra facilitar alguma explicação,
mas depois eu gostaria que vocês
refizessem tudo como privado
naturalmente, tá, pra manter a ortodoxia da orientação a objetos.
Isso vai permitir que vocês retrabalhem e revisitem o código, tá,
de maneira mais atenciosa.
Aqui, uma coisa importante a ser dita é o seguinte, tá,
numa lista encadeada
que eu imagino que vocês já começaram a ver lá em estrutura de dados.
Se não viram, verão em algum momento dado, né.
O fato é que uma lista encadeada, uma das maneiras de contemplá-la
é fazendo com que cada elemento que participe da lista
colabore na lista.
Então, aqui, por exemplo, a própria Disciplina tem o pProx
de ponteiro Disciplina.
Imaginem que tenha 3 elementos na lista.
Três Disciplinas na lista, tá, que vai estar em Departamento.
Então, o primeiro aponta pro próximo
o segundo pro próximo e o terceiro aponta pra ninguém.
Aponta pra nulo.
Também numa lista encadeada, quem contém
a suposta lista, ou o que representa a lista,
ele conhece o primeiro elemento ou o elemento atual, ou último, né.
O último que foi inserido, atual nesse sentido que ele foi o último a ser inserido.
Então, assim que se cria uma lista.
Nessa abordagem que a gente vai utilizar, quem tem a lista conhece o primeiro elemento
e o atual que representa o último
e cada Disciplina conhece o próximo.
E através de próximo, próximo, próximo que você faz o encadeamento
entre os elementos, daí o termo lista encadeada.
Nesse caso, simplesmente encadeada, porque ele conhece só o próximo.
Não conhece o anterior, conhece só o próximo, insisto.
Muito bem. Como é que a gente coloca isso em termos de código.
Antes de colocar em termos de código
eu quero dizer que essa abordagem aqui, tá,
da própria Disciplina conhecer o próximo
não é, necessariamente, a melhor abordagem
vocês vão perceber em slides subsequentes que a gente vai melhorar isso drasticamente.
A gente vai deixar isso muito mais elegante,
mas pra um primeiro momento do entendimento
a gente pode usar essa abordagem, vamos dizer aqui, mais simplória.
Muito bem.
Isso dito, avancemos pro conjunto de
slides que tá aí exposto que nos traz o quê?
O código.
Legal.
Se você olhar aqui, tá aqui a classe Disciplina.
Respeitando o modelo, aqui eu tô dizendo que, pelo modelo que eu fiz, tá,
tenho que ver se o modelo respeita os requisitos,
mas pelo modelo que eu fiz é uma agregação não-direcional,
ou seja, não tem seta aqui.
Se não tem seta, isso significa que a Disciplina, vai sim, conhecer o Departamento.
Tá ali, ó.
A Disciplina tem um ponteiro pra Departamento.
pDeptoAssociado ponteiro de Departamento.
Insisto, se você olhar aqui a agregação não tem seta
Se não tem seta, isso significa que quem agrega conhece o agregador.
Nesse caso aqui, a Disciplina tem um pDeptoAssociado, ponteiro Departamento
pra, justamente, conhecer o agregador que é o Departamento.
Por isso que eu fiz aqui um #include "Departamento.h"
tem um pDeptoAssociado, ponteiro Departamento.
e aqui o set e get Departamento.
Aqui, inclusive, eu tô fazendo uma espécie de rastreabilidade
dos requisitos no próprio código.
Crie uma classe Disciplina. Associe cada Disciplina a um Departamento.
Não estava aqui, tá. Bastava eu ter prestado mais atenção.
Muito bem.
Isso considerado, agora a gente já tem estrutura
pra Disciplina conhecer o Departamento
e agora a gente quer que o Departamento conheça as Disciplinas,
ou seja, tenha a lista encadeada de Disciplinas.
Cada Departamento deve ser capaz de armazenar uma lista de disciplinas.
Para tal, usando a técnica de lista encadeada,
o Departamento vai ter dois ponteiros de Disciplina.
Um chamado pDisciplPrim e o outro chamado pDisciplAtual
que, no meu discurso, não raro, eu vou chamar de pPrimeiro e pAtual pra facilitar.
Mas o nome é pDisciplPrim e pDisciplAtual
no meu discurso as vezes pPrimeiro e pAtual só pra
como apelido pra facilitar a oratória.
Tá, aí, então tá cumprido.
Cada Departamento deve ser capaz de armazenar uma lista de disciplinas.
Esta lista deverá ser simplesmente encadeada.
Tá aqui, ó.
pProx do tipo asterisco Disciplina.
Aqui, em termos de código, eu já privei estes ponteiros.
Então, eu poderia, lá no modelo, já atualizar eles pra privado.
Aqui que eu continuo deixando público. Tá vendo, ó?
Isso aqui é uma heresia, tá.
Insisto, vocês vão ter que pegar isso aqui e colocar depois lá pra dentro,
E criar um set e get próximo.
Bem entendido.
Mais uma vez
pProx é do tipo ponteiro Disciplina.
Por quê? Porque cada Disciplina vai colaborar na...
na composição da lista encadeada conhecendo o seu próximo.
Aqui no próximo slide inclusive destaco em vermelho
quais que são os elementos de Departamento e Disciplina
que vão permitir colaborar no sentido
de compor a lista simplesmente encadeada em Departamento.
O Departamento colabora, tendo um pPrimeiro e um pAtual,
tendo o incluaDisciplina() e o listeDisciplinas().
Funções fundamentais pra nós, a gente vai trabalhar com elas durante essa aula.
E a Disciplina tem... cada Disciplina tem um pProximo
permitindo conhecer seu próximo.
Aqui eu pus um exemplo de objeto de Departamento que é o DAELN.
Você já percebe que ele tem o pPrimeiro e tem o pAtual.
Aqui, você tem um exemplo de Disciplina que tem o pProximo.
Vejam que tem a reticências ali e tem a reticências aqui
Isso significa que tem mais coisas dentro do objeto,
conforme vocês tão observando pelas próprias classes obviamente.
Aqui eu tô destacando o que me interessa, bem entendido.
Bom, se eu tenho aí, o Departamento.h
e tenho o Disciplina.h, eu vou ter os respectivos .cpp.
Não é isso?
Eu quero que vocês prestem atenção numa coisa.
A Disciplina incluiu o Departamento?
Incluiu, né.
"Departamento.h", ó.
Por quê? Porque ela teria até um ponteiro Departamento associado.
Isso teria o seu Departamento.
Se o... se a Disciplina já incluiu o Departamento.h
o Departamento não pode incluir a Disciplina.h.
Simplesmente não pode.
Ele fica interditado.
E daí como é que faz? Você tem que usar aquele recurso
que já foi explicado outrora
em exposição anterior.
Você tem que redefinir a classe Disciplina aqui, ó.
Class Disciplina;
E aí, você usa o artifício...
a parte subsequente do artifício
que é uma vez tendo redefinido a classe Disciplina
no Departamento.h.
Na definição aqui, no sentido, só de memento
de dizer olha, fique tranquilo que
eu não tô podendo incluir a Disciplina agora aqui,
mas já já vou incluir em lugar pertinente.
E que lugar pertinente é esse?
Justamente, o Departamento.cpp.
Vejam que ali no Departamento.cpp eu incluo a Disciplina.h.
Mesma coisa acontece com a classe Universidade, ó.
O Departamento precisava incluir a Universidade pra ter o pUniv.
Só que a Universidade já tinha incluído o Departamento,
então o Departamento ficava impedido,
por isso que usa o artifício.
Redefine aqui, sucintamente, a classe como um memento,
uma memória, uma observação
e inclui o Universidade.h no respectivo .cpp,
nesse caso, o Departamento.cpp.
Legal.
Aqui na construtora
do Departamento, eu tô aterrando os ponteiros pPrimeiro e pAtual.
Tanto na construtora quanto na destrutora.
Se tem ponteiro a gente aterra.
Isso é uma regra.
Aqui tem set e get nome do Departamento, coisa conhecida.
Set e get Universidade, coisa conhecida do exercício anterior.
Quem tá fazendo os códigos olha e se simpatiza com isso, porque já viu.
E, aqui, tão as duas funções que a gente vai trabalhar bastante nessa aula
que é o incluaDisciplina().
É isso que permite compôr a lista encadeada
Veja que a Disciplina, a lista dela se compõe de endereços,
ponteiros Disciplinas.
O fato do Departamento ter uma lista de Disciplinas
significa que ele tem os apontamentos das Disciplinas por algum meio.
E esse meio é a lista encadeada
que a gente vai expor aqui
e o Departamento tem, na verdade, o primeiro e o atual.
Ele conhece os outros com a ajuda das próprias Disciplinas através do ponteiro pProximo
que a gente vai discutir daqui a pouco.
Aqui tem a listagem de Disciplinas
Através do pPrimeiro
e Departamento de pProximo Disciplina
a gente consegue navegar na lista de Disciplinas, tá.
Insisto, a gente vai, daqui a pouco, salientar essas
duas funções aqui, e vamos poder trabalhar com elas, tá.
Ainda, do ponto de vista de .cpp
a gente olhou aqui então o Departamento.cpp,
mas também temos o Disciplina.cpp.
Tá aqui, Disciplina.cpp.
pDepartamentoAssociado e pProximo,
cada Disciplina tem um pProximo,
estão aterradas com nulo, por quê?
É mântrico.
Se você tem um ponteiro, ele tem que tá aterrado com nulo
no início e, preferencialmente, ser aterrado,
aliás via de regra ser aterrado como nulo na destrutora.
Construtora e destrutora aterrando com nulo.
A classe Disciplina, vou voltar aqui dois slides.
Vocês viram que ela tá aqui, né.
Bom, aqui, eu nem falei de obviedades, né.
Eu nem tinha falado pra vocês dos atributos
Tem o atributo id, o nome, um área de conhecimento
falei mais do ponteiro aqui departamento associado
e do pProximo, mas ele tem o que uma classe tem que ter, né.
Atributos, construtora e destrutora, sets e gets, tá,
e aqui tem, obviamente, o set e get Departamento
que é fundamental pra Disciplina poder apontar em cada Departamento
Departamento conhece uma série de Disciplinas
e cada Disciplina conhece o seu Departamento.
Legal.
Voltando aqui, então, pro nosso Disciplina.cpp.
Tá aqui a construtora, tá aqui a destrutora
setId, getId, setNome, getNome,
setDepartamento, e getDepartamento.
O setDepartamento recebe um ponteiro de Departamento,
endereço de Departamento via ponteiro, bem entendido.
E aí ele pega esse endereço que está no ponteiro
e armazena no pDpto associado para que a Disciplina conheça o seu Departamento.
Isso é uma primeira versão, tá. Isso vai evoluir, já fique isso registrado.
Muito bem. Então, aqui a gente viu a classe Departamento.h,
a classe Departamento com seu .h e seu .cpp
Vimos a classe Disciplina, o seu .h e o seu .cpp,
já passando nessa fase aqui de implementação.
Outra coisa que a gente vai depois desse exercício
é uma pequena mudança na classe Principal.
Eu organizei um pouco a classe Principal.
A classe Principal tem um série de objetos que a gente tem criado aí,
de Universidade, de Departamento, de Professores, de Disciplinas, tá.
Aqui, em algumas versões do código, eu tinha colocado mais Departamentos inclusive, tá.
Nada obsta de vocês recuperarem aqueles Departamentos e colocarem aqui.
Até pra... como memento, lembrança disso
vou deixar uma reticências aqui, tá, que a gente já tinha criado outros Departamentos
que podem tá contemplados aí sem problema nenhum.
Então, estão aqui as nossas Universidades,
nossos Departamentos, nossos Professores, nossas Disciplinas,
diaAtual, mesAtual e anoAtual que...
que usa lá na construtora recuperando a data.
Vocês devem perceber... ter percebido pelos slides anteriores
que a construtora tava ficando grande.
Eu tinha uma seção que inicializava Universidades
tinha uma seção que inicializava Departamento,
uma seção que inicializava Professores
e uma seção... um pedaço do código da construtora que inicializava Disciplinas.
Pra organizar melhor isso, pra não deixar tudo um código tripão, né.
Código espaguetão.
Dentro do Principal,
o que eu fiz foi, simplesmente, dividir o Principal em um conjunto de funções menores.
Ali... essa função Principal, aqui, construtora
ela vai recuperar a data do sistema,
daí ela vai chamar a função inicializa
que por sua vez, chama a função inicializaUniversidades
InicializaDepartamentos, InicializaProfessores, InicializaDisciplinas
que são autoexplicativas.
Essas funções pegaram e organizaram o código da construtora.
Cada qual faz o seu pedacinho de código, né, no seu âmbito,
sem deixar aquele código enorme, gigantesco, dentro do Principal.
Aí que fatorou, que dividiu o Principal
a construtora, né. O código da construtora, melhor dizendo.
em uma série de funçõezinhas menores pra fins de organização.
Mesma coisa eu fiz com o executar.
Executar agora chama o CalcIdadeProfs,
Universidade onde os Professores trabalham,
Departamento onde os Professores trabalham
e o listagem de Disciplinas por Departamentos que é uma função nova.
Que vai permitir, eu, a partir de um Departamento, por exemplo, o DAELN,
que pode, por exemplo, incluir essas Disciplinas.
Eu posso pegar ali e fazer um DAELN.listar, ou algo assim,
Como é que é a função de listagem do...? Liste Disciplinas, tá.
Posso vir aqui e fazer... lá dentro do código, né.
DAELN.ListeDisciplinas.
que vai listar essas Disciplinas que estão incluídas nessa lista encadeada.
Novamente, aqui, simplesmente, eu dividi o código
separei o código, que tava um tripão essas duas funções, em funções menores.
Simples assim.
Melhorando a organização.
Tá lá, ó.
Principal, leitura de data, chama o Inicializa.
Inicializa chama o InicializaUniversidades, InicializaDepartamentos,
InicializaProfessores e InicializaDisciplinas.
O que faz o inicializa das Universidades? Coloca nome nas Universidades.
O que faz o InicializaDepartamentos?
Coloca nome nos Departamentos.
Não é isso?
Talvez tenham mais coisas aqui, inclusive, ó.
Deixei reticências.
O que faz o InicializaProfessores?
Ele inicializa os Professores, tá.
Ah, professor, por que não tá chamando a construtora?
Você pode chamar a construtora.
Aqui, eu optei por chamar a função Inicializa que é pública, tá.
Inclusive, a construtora sem parâmetros, com certeza tá sendo chamada,
aqui, né, de maneira implícita.
Lembrar que vocês podem ir lá
e fazer aquela estratégia de chamar explicitamente.
Rogo que façam, inclusive, na versão de vocês.
Aqui ainda, voltando pra inicializaProfessores(),
além de chamar a função inicializa() de cada Professor
eu associo o Professor à Universidade.
Isso aqui é uma função que eu quero ter na sequência mas não tenho ainda,
então é por isso que tá comentado,
e aqui tem o setDepartamento().
Bom, inclusive se a função não tem ainda
nada impede de eu vir aqui e eliminar isso aqui.
Depois a hora que tiver a gente coloca esse código aí.
Muito bem.
Suponho que era isso que eu tinha pra dizer com relação a esse slide corrente.
Assim sendo, avancemos um tantico aqui.
Ainda estamos no Principal.cpp, tá.
Então a gente viu parte das funções de inicialização, mas não viu todas.
Aqui nós temos o InicializaDisciplinas().
Essa função é interessa particularmente pra nós, tá.
Eu coloco o nome das disciplinas e agora que as disciplinas estão nomeadas
Eu faço o DAELN incluir o endereço
de cada uma dessas Disciplinas pra compor sua lista encadeada de Disciplinas.
Aqui tem mais código que eu não tô mostrando ainda,
mas vou mostrar muito em breve.
Lembrem-se que os métodos de uma classe
eles tem acesso a todos os atributos da classe.
O DAELN, por exemplo, é um atributo da classe
que é acessível tanto aqui no InicializaDisciplinas()
como em qualquer outra função-membro da classe.
Então, essa função é particularmente importante pra nós e a gente já volta nela.
Inclusive, essa aqui é uma primeira versão, então tem uma segunda versão, obviamente.
O CalcIdadeProfs,
que vai ser chamado aonde? No Executar().
Universidades onde os Professores trabalham,
Ali ó.
Simao.OndeTrabalho(), Einstein.OndeTrabalho() e Newton.OndeTrabalho().
Chamado aqui.
Departamento onde os Professores trabalham chamado logo em seguida.
Tá definido ali, ó.
E, por fim, liste disciplinas por Departamento.
Por enquanto só tem um Departamento que vai ter uma Lista Disciplinas,
que é o DAELN. DAELN.listeDisciplinas().
Pessoal, agora é muito importante esse próximo momento do código,
porque é o momento que eu vou mostrar pra vocês
como é que de fato ocorre a lista encadeada
com essa infraestrutura que a gente criou.
A hora que eu incluo o endereço de cada Disciplina no DAELN
eu começo a montar a lista encadeada usando os ponteiros lá
o pProximo, eventualmente o pAtual.
Na verdade, o pAtual também e pProximo.
Eu vou destacar essa função aqui, inclusive, vou mostrar o código que tem na reticências ali, tá.
Olhe lá
Aí está.
Aqui, então, eu tenho a coisa completa.
Eu faço o DAELN conhecer todas as Disciplinas
e faço cada Disciplina conhecer o DAELN.
Fazendo aquela agregação não-direcional.
Agregação onde que o agregado conhece o agregador.
Através de ponteiros eu tô animando essa agregação
O DAELN, então, está incluindo as suas Disciplinas
cada Disciplina vai conhecer o DAELN, bem entendido.
Aqui tem reticências, mas porque tem mais código.
É aquele código que estava no slide anterior,
, ali, das demais funções.
Pessoal, o que vocês tem que imaginar aqui no sistema é o seguinte,
nesse momento do sistema, nesse momento aqui dessa função,
se você olhar em termos de execução,
o que aconteceu?
Eu rodei o código. Rodou a função principal.
A função principal, criou o objeto Principal.
A função main, criou o objeto Principal, melhor dizendo.
Esse objeto Principal criou todos os seus objetos agregados,
os Professores, as Universidades,
os Departamentos e as Disciplinas.
Inclusive essas que estão salientadas aqui.
Também já rodou a construtora de cada uma delas.
Inclusive o Principal também rodou sua própria construtora
chamando várias Inicializas
chegando daí, em algum momento dado,
aqui no inicializaDisciplinas().