Aqui tem um exercício, tá,
que o seguinte:
Cada Departamento deve ser capaz de armazenar uma lista de Disciplinas.
Vocês já fizeram esse exercício duas vezes.
Uma vez vocês fizeram usando a solução
aonde a própria Disciplina
ela tinha dentro de si o pProximo e o pAnterior
e isso funciona porque lá era um contexto
de um pra n, n pra 1,
mas não era elegante.
Aí vocês fizeram,
à luz do que eu pedi na última
exposição, na última aula,
vocês criaram pra essa solução, ainda que um pra n,
um Elemento Disciplina pra gerenciar cada Disciplina em cada lista.
Pra fins de elegância e respeitar
o desacoplamento natural da orientação a objetos,
como você se inspira no mundo real.
Bom, agora eu tô pedindo pra evoluir um pouco esse exercício,
fazendo o seguinte
A classe Disciplina, entretanto,
não deverá possuir um ponteiro para o Próximo
Isto deverá estar em uma classe associada chamada ElDisciplina
relaciona, agora, a ListaDisciplina
e não mais ao Departamento.
Então, tal qual a gente desacoplou a lista de Alunos
da classe Disciplina
Agora, a gente vai desacoplar a lista de Disciplinas do Departamento.
Ah, mas por quê, professor?
Segundo, gente, que eu posso precisar
ter listas de Disciplinas em outros lugares.
Aqui, por exemplo, tá.
Sei lá. Eu quero ter uma lista de todas as Disciplinas da Universidade.
Então, eu posso ir lá na classe Universidade que eventualmente eu vou criar
aliás, que já existe,
colocar lá um objeto chamado
ListaTotalDisciplinas do tipo ListaDisciplinas.
Vou voltar aqui, tá. Fazer um discurso ainda mais concreto
Veja aqui, por exemplo, aqui é Disciplina, tá.
eu tenho ObjLAlunos Lista Alunos.
Imagine que o Departamento quer uma lista de Alunos
eu posso criar lá um objeto no Departamento, tá.
ObjTodosAlunos do tipo ListaAlunos.
Não impede. Por quê? Porque a classe é independente.
Os objetos que depois vão ser instanciados conforme...
criados conforme o contexto que for necessário,
mas a classe ela é desacoplada de Disciplina
permitindo que ListaAlunos seja usado em, além de Disciplina, em outros lugares.
No Departamento, na Universidade mesmo,
no sistema como um todo, inclusive.
Ah, professor, então eu posso, por exemplo, ter, como isso aqui é um sistema de Universidades,
eu posso ter uma lista de todos os Alunos de todas as Universidade na classe Principal?
Pode.
Assim como depois que fazer esse exercício aqui
vocês vão poder ter, na classe Principal, uma lista de todas as Disciplinas
de todos os Departamentos e todas as Universidades.
Basta você criar, na classe Principal, uma lista de Disciplinas lá,
usando a classe ListaDisciplinas que vocês vão criar.
Então, o que eu gostaria de vocês, nesse momento preciso,
é o seguinte:
queria que vocês fizessem uma pausa no vídeo
e resolvessem esse exercício que tá em tela.
Primeiro atualizando o modelo de vocês.
Supostamente não vai ter muito problema, porque vocês
podem se inspirar nesse modelo aqui.
Claro que agora vai entrar uma classe aqui,
Departamento que... bom que já existia, né, vocês vão só ajustar o modelo, tá.
E fazer a criação de uma nova classe aí
ListaDisciplinas que vai se relacionar com o ElDisciplinas
que por sua vez se relaciona com a Disciplina ela mesma.
Então, vai ter aqui a classe Departamento
tem um relacionamento com Disciplinas.
vai ter aqui o ElDisciplina
e vai ter aqui o ListaDisciplinas, tá,
com os relacionamentos apropriados.
Depois que vocês fazerem o modelo
façam também o código.
Fazendo os ajustes.
Como vocês já tem boa parte desse código pronto.
Vocês vão criar uma nova classe desacoplante
que é o ListaDisciplinas.
Supostamente, ele vai ser mais um rearranjo
de posicionamento de códigos
e de ajuste de relacionamentos, tá.
Não vai tomar tanto tempo.
Claro que vocês criem e mantenham a versão de código que vocês tem.
Criem uma nova versão, como sempre,
e nessa nova versão faz
as novas demandas aí, solicitadas.
Gastem uma meia hora, uma hora que seja
pra fazer esse exercício
e aí retomem aqui o meu vídeo.
Bom, pessoal, suponde que vocês já bem fizeram o exercício, tá.
Refletiram, avançaram e chegaram a solução a termo.
Vamos ver uma solução, tá.
À luz do diagrama de classes que vocês fizeram, tá.
Vocês devem, muito que provavelmente, cair num código assim.
Aonde você vai ter o Departamento
e o Departamento não vai mais ter dentro de si
o pElDisciplPrim nem o pElDisciplAtual
O que ele vai ter dentro de si é um pObjLDisciplinas.
é o pObjLDisciplinas.
Naturalmente.
Tal qual a Disciplina tinha o pObjLAlunos.
Aqui, entretanto, há um porém.
Vejam que aqui não é um objeto criado
estaticamente dentro da classe.
É um ponteiro.
Um ponteiro ListaDisciplinas.
Mas por quê, professor? Faz muito mais sentido criar aqui
um objeto em vez de um ponteiro.
Faria, se não fosse essa situação aqui
Vejam que conforme o código foi criado
a Disciplina, a classe Disciplina, o Disciplina.h
incluiu, por assim dizer, o Departamento.h.
Então, o Disciplina.h incluiu o Departamento.h mais pragmaticamente falando.
Se o Disciplina.h incluiu o Departamento.h,
por sua vez, o Departamento.h não pode incluir o Disciplina.h.
Aí eu tenho que usar aquela estratégia que eu já tô cansado de repetir.
Redefinir a classe Disciplina aqui
e incluir o respectivo .cpp,
nesse caso, no Departamento.cpp.
Bom, como a classe ListaDisciplinas
depende de Disciplina,
aqui eu tenho que continuar usando a mesma regra por propagação.
Eu tenho que redefinir a classe ListaDisciplina
e incluir no respectivo .cpp
que é precisamente o Departamento.cpp.
Então, atenção com isso.
Quando eu uso essa estratégia aqui,
pra escapar da questão dos includes recursivos,
estratégia essa já discutida em slides anteriores
Aí, muito embora, ela permita escapar da situação posta.
Ela tem uma restrição.
Ela não permite que eu crie estaticamente, aqui, nesse momento o objeto.
Ela não permite por um motivo muito preciso.
Eu tô apenas dizendo pro compilador: olha compilador,
fica tranquilo aí que uma hora eu vou contar pra você
aonde está a classe Disciplina e a classe ListaDisciplinas.
Só que eu não contei ainda.
Se eu não contei ainda, ele não consegue criar objeto,
ele consegue no máximo acreditar que eu posso ter ponteiro disso.
Ora, eu aceito que eu vou ter ponteiro disso,
mas como não sei ainda o que que é, então eu não posso deixar você criar objeto.
Mas, daí, no respectivo .cpp
que é o Departamento.cpp que eu mostro no próximo slide, slide número 16
Tá aqui, ó.
Agora sim, eu inclui a disciplina e a ListaDisciplinas.
Inclusive, muito embora,a ordem aqui não afete
a organização das coisas, tá.
Só pra fins pedagógicos.
Vamos colocar aqui e aqui, sim, .h.
Bom, retificando meu discurso.
Agora sim está feito o include de Disciplina.h e de ListaDisciplinas.h
no .cpp pertinente que é, aqui, o Departamento.cpp
Agora, sim, eu posso criar, ainda que dinamicamente,
à luz daquele ponteiro, um objeto.
Eu crio, ali, dinamicamente e não estaticamente,
um objeto de ListaDisciplinas, tá.
Insisto, foi obrigado a usar esse estratagema
em função de utilizar o artifício lá
de escapar, de escapamento do... dos includes recursivos.
Então, usei esse artifício. Criei dinamicamente aqui.
Bom, se eu fiz um new, eu vou ter que fazer um delete no final.
Aqui eu tô testando, tá.
Isso aqui é equivalente a fazer esse if pObjLDisciplinas é diferente de nulo, tá.
Eu sei se ele é diferente de nulo. Quando ele for diferente de nulo eu deleto ele,
porque eu não posso deletar coisa nula obviamente.
Bom, e aí como é que eu uso, professor, esse objeto?
Ora, se você criou ele dinamicamente,
você sabe como é que funciona, tá.
Você tá acessando ele via um ponteiro.
Se você tá acessando ele via ponteiro, você não usa o operador de ponto,
usa o operador de seta que tá ali, ó.
Operador de seta.
E o resto fica tudo o mesmo.
O que interessa aqui é que o nosso código ficou muito mais decente.
Porque agora a classe, até posso voltar um pouquinho aqui.
Agora a classe Departamento não tem mais
insisto, um pElDisciplPrim e um pElDisciplAtual
são ponteiros, então olhando pra gente não é intuitivo.
A hora que você olha pra ele, tá.
Agora a hora que você olha no Departamento
e você vê que tem uma lista de Disciplinas, isso é intuitivo.
Aqui estão as implementações com os nuances que eu falei, tá.
Do uso, aí, de alocação dinâmica
por causa da situação posta.
Se é alocação dinâmica de memória
eu não uso mais o operador de ponto, saliento que usa o operador de seta.
Conforme vocês tão vendo aqui.
Legal.
Agora eu tenho aqui a classe ListaDisciplinas.
que ela sim, faz todo sentido daí,
porque daí você olha no contexto você entende
ListaDisciplinas.
pPrimeiro e pAtual. Ah! Lista encadeada.
Nesse contexto faz sentido.
E aí, você tem ali, então, pElDisciplPrim e pElDisciplAtual
ponteiros de ElDisciplina como não poderia deixar de ser.
Aqui, essa ListaDisciplinas tem uma construtora
com parâmetros com valor default.
O que faz a vez do construtor sem parâmetros, tá.
Inclusive, se você olhar lá a construtora
da ListaAlunos, ela tem uma imperfeição.
Porque ela só tem uma construtora
com parâmetros sem valor default.
Assim, no final das contas, eu não estou definindo na ListaAlunos,
já fazendo uma ressalva aqui,
a construtora sem parâmetros.
Até vou voltar lá na ListaAlunos, tá.
Eu tô no slide 17, eu vou fazer um jump
pro slide 10.
Olha aqui, ó.
Aqui tem um pecado, tá.
ListaAlunos não tem uma construtora sem parâmetros
ou coisa que o valha.
Ou coisa que o valha é o valor default nos parâmetros.
Então, uma maneira de resolver isso é colocar valor default aqui.
Volto pro slide 17.
E aqui no slide 17, já tá mais correto, ó.
Ele já tem valores default nessa classe em questão
que é a ListaDisciplinas que eu acabei de comparar com a classe ListaAlunos lá, tá,
pra fazer a crítica na classe ListaAlunos
que não tem os valores default,
mas deverá ter na versão que vocês vão criar pra vocês, aí,
ou que vocês tão criando aí, cada qual na sua base de experimentação, né.
Criando o seu sistema
numa disciplina aqui, orientada a projetos igual a nossa.
Legal, gente.
Obviamente que agora eu tenho a classe ListaDisciplinas
é aqui que vai ter o que é necessário,
do ponto de vista do aterramento de ponteiros,
o delete do ElDisciplina
de cada um deles, no âmbito aqui da desalocação
Naturalmente que aqui vai acontecer a inclusão de códigos.
Se a gente é perfeccionista a gente é perfeccionista, né.
Vou fazer o ajuste aqui.
Veja esse ajuste que estou fazendo aqui, por exemplo, tá.
Vou deixar o código um pouquinho assim, só pra eu fazer um aposto.
Imaginem que eu não criei a ListaDisciplinas,
mas, ainda assim, eu precisei ter uma lista de Disciplinas
no Departamento, na Universidade e no sistema como um todo.
No Departamento, porque eu tenho a lista de Disciplinas no Departamento.
Na Universidade, porque eu quero ter uma lista de todas as Disciplinas dos Departamentos.
E no sistema, porque eu quero ter uma lista
de todas as Disciplinas, de todos os Departamentos e de todas as Universidades.
Pra, sei lá eu, fazer mobilidade de estudante,
melhorar o aproveitamento de Disciplinas entre Universidades próximas.
Então, imaginem que eu não tivesse criado essa lista de Disciplinas.
Eu ia ter que ter um código imbricado
enjambrado dentro da classe Universidade,
dentro da classe Principal
e dentro da classe Departamento
como eu tinha até agora há pouco, inclusive, em Departamento.
Essa colocação que eu tô fazendo, aqui, agora,
como o código ele tá replicado em três lugares, ele vai ter que fazer essa implementação nos três lugares,
mas, felizmente, como agora eu criei a classe ListaDisciplinas
e depois Departamento,
eventualmente Universidade, eventualmente a Principal,
vão apenas instanciar objetos, tá.
Essa implementação já vai valer pra todos.
Bem entendido.
Vamos aqui,
colocar
a coisa
dentro do if
pertinente.
Bom, aqui a gente vai identar...
aqui a gente vai identar
como a gente sempre faz
o código, né,
porque o código identado
é elegante e fica mais fácil de entender.
Muito bem.
Bom, ali se você olhar o if acima
o if tem uma série de situações que ele tá analisando.
Provavelmente à luz dos requisitos
que eu fui estabelecendo pra vocês com o tempo.
Então, eu tenho aqui o contador de Disciplinas.
Aparentemente tem um número máximo de Disciplinas agora.
Testando se os ponteiros não é nulo.
Tô testando se o número de Disciplinas é diferente de -1,
ou seja, eu tenho uma lista que não pode ter sido criado
com número vazio, né. Ela tem que ser...
Ah, não. Na verdade, aqui, é um ou, tá, gente.
Então, prestem atenção no que tá acontecendo aqui.
Aqui eu tô testando o contador.
Tô testando se o contador de Disciplinas é menor que o número de Disciplinas
e se o ponteiro não é nulo.
Ou se eu deixei -1, significa que eu tenho um número ilimitado de Alunos.
Professor, mas isso é possível? Um número ilimitado de alunos em uma disciplina?
Eu pego uma Disciplina online,
aonde as avaliações são todas automatizadas
e as aulas são gravadas e etc, tá.
Uma disciplina mais informativa do que formativa, por exemplo.
Aí, talvez seja possível.
Mas tá aqui então... ou... ou até o número máximo, sem ponteiro nulo
Ou eu vejo que é -1 e isso interpreta como um número free, né.
Quantidade free de alunos.
Um ponteiro diferente de nulo.
Então, é essa a decisão ali tomada.
Uma vez que passou os condicionantes pra poder fazer
a criação de ElDisciplina e tudo mais, pertinente, então,
eu toco esse processo aqui.
Então, tá aí, feito o ajuste no código, tá.
Ajuste, esse, que eu tenho certeza que vocês vão fazer no código de vocês também.
Muito bem.
E aqui voltamos pro Modo Exibição.
Já salvei ali as alterações que eu fiz.
Fiquei feliz com essa nova organização.
Permite também exemplificar
a importância de você ter uma Lista de Disciplinas.
Se você tem uma Lista de Disciplinas
tudo que tá em Lista de Disciplina, tá nesse objeto.
Qualquer correção que eu faça na lista,
ela se reflete pra todas as instâncias depois que eu tiver.
Seja as listas que estão nos Departamentos,
seja as listas que estão nas Universidades, seja as listas que está
no Principal, ou alhures, em outro lugar.
Aqui, tô mostrando a classe Elemento Disciplina que não tem novidade pra vocês, tá.
Vocês já fizeram isso num exercício.