Em termos de UML, você modela assim, ó.
Você tem a classe Pessoa
Isso aqui, no caso do StarUML, esse hashtag aqui, sustenido,
ele denota protegido.
E essa seta, ou esse triângulo aqui bem formado, na base da seta.
na base, não, na cabeça da seta,
ele denota a Herança, tá.
Isso aqui então é a sintaxe de herança em UML.
O Professor herda de Pessoa, e simples assim.
E aí, aqui você coloca os métodos da classe Professor
e obviamente, tá, aqui não tá os ponteiros ainda
porque eu queria destacar a questão da derivação, tá,
mas vocês podem melhorar aqui, já numa visão de Projeto
e colocar os ponteiros que já estão no código, positivo?
Então, colocar os ponteiros aqui.
Se a gente olhar, em termos de Análise
Tá aqui uma visão de como o nosso Sistema tá ficando.
Então, você tem o Professor ali derivado de Pessoa.
Professor conhece a Universidade.
Professor conhece o Departamento
Aqui como é Análise, eu não coloquei os ponteiros ainda, né,
é na parte de Projeto que a gente procura colocar os ponteiros.
E tá aqui também o fato da Universidade
agregar fortemente de 1 a 50 Departamentos, tá.
Agora eu vou sair de um Diagrama de Análise e vou ir pra um Diagrama de Projeto,
ou seja, um diagrama que visa mais a implementação.
Então, tá aqui. Agora os ponteiros aparecem, né.
Ponteiro pUnivFiliado pra animar essa associação,
e ponteiro pDptoFiliado pra animar essa associação.
Aqui, foi interpretado essa agregação como agregação-fraca, né.
Em termos de Projeto é uma agregação-simples ou fraca.
São equivalentes os termos.
Porque será implementado por meio de ponteiros.
Isso aqui já foi discutido, tá.
Nessa interpretação, como eu tô vendo ali um ponteiro
não tô vendo direto o objeto instanciado dentro,
eu interpreto como agregação-fraca,
mas a gente já sabe que também é possível você fazer uma outra interpretação, tá.
Respeitando a origem, lá na origem lá, é uma agregação-forte.
Então, mesmo que eu implemente por ponteiro, eu vou continuar usando agregação-forte aqui
e usando essa interpretação, então, nesse viés de respeitar
como a relação está na origem e lá na Análise.
Obviamente que o importante é que você se coloque de acordo
consigo mesmo e com sua equipe
em como é que vocês vão tratar esse tipo de situação posta aqui, tá.
Se por agregação-fraca ou simples, no tocante ao projeto, tá.
Aqui eu tive que colocar como fraca, tá, até pra gerar polêmica, tá,
mas eu mesmo, sinceramente, preferiria colocar isso aqui como agregação-forte
inclusive, em termos de Projeto, apesar de estar utilizando
ponteiro lá, só pra constar.
Bom, pessoal, agora tem um pequeno exercício, né.
Inevitavelmente. Que é, tanto em termos de UML
quanto em termos de código
você criar uma classe Aluno que seja derivada da classe Pessoa.
A classe Aluno terá uma atributo inteiro chamado RA
que é um acrônimo, aí, de um Registro Acadêmico.
Agora se vocês quiserem, vocês podem fazer uma pausa no vídeo
e tentar resolver o exercício em termos de UML e em termos de código.
Preferencialmente, integrando já
essa nova classe no modelo geral
que vocês estão fazendo
como o código geral, aí, também que vocês tão fazendo, tá.
Eu imagino que a essa altura do campeonato, vocês já tenham a versão
pro Sistema Acadêmico de vocês, tá, em desenvolvimento,
tanto em termos de modelo, bem entendido, lá no StarUML ou coisa que o valha
e no projeto em C++
no Microsoft Visual C++ ou no CodeBlocks ou coisa que o valha.
Bom, eu aqui em ato contínuo vou apresentar a solução do exercício.
Então, tá ali, ó. Aluno é derivado de Pessoa.
Criei uma nova classe, trazendo aqui
a denotação de que Aluno é um subtipo de Pessoa.
Ou uma especialização de Pessoa, se você quiser enxergar assim.
Aqui eu pus um comentário, tá,
pra pessoa entender que RA é Registro Acadêmico.
Então, comentários eu posso, em termos de UML, associar
a várias coisas, tá. Eu posso plugar ele
em relacionamentos, eu posso plugar ele em classes e assim vai, tá.
Isso aqui, na verdade, é um pontilhado, tá.
Aqui é um probleminha de impressão, aqui, do slide,
mas tudo bem.
Outra coisa interessante, tá, é que em herança
não se usa cardinalidade.
Porque ele é visto como um relacionamento muito mais estrutural,
no sentido que todo Aluno vai ser derivado de Pessoa.
Todo Professor vai ser derivado de Pessoa.
Então, ou melhor dizendo, tá.
Cada Professor também é uma Pessoa
e cada Aluno também é uma Pessoa.
Assim a cardinalidade tá implícita
se a gente parar pra pensar mais profundamente.
Isso considerado, vamos pro código.
E aqui está o código.
Classe Aluno "dois pontos" public Pessoa.
Então aqui eu tô dizendo que a classe Aluno é derivada publicamente,
derivada publicamente de Pessoa.
Eu já explico o que que é essa derivação pública, tá.
Mas o fato é que se tem "dois pontos" public você já tem que entender que é uma derivação.
Ali, eu tô incluindo a classe Pessoa, aliás, eu tô incluindo a Pessoa.h,
aonde tem a classe Pessoa, obviamente, porque... porque Aluno é derivado de Pessoa.
Tá aqui em privado. Professor por que não é protegido aqui?
Porque a classe Aluno é base.
Perdão, a classe Aluno é derivada.
Quem é base é Pessoa.
Lá na base é que tem que ter os elementos protegidos.
Aqui eu tenho construtora sem parâmetro, ou equivalente,
ou seja, com os parâmetros todos com valor default.
E aqui tem uma construtora com parâmetros.
Opa, professor,
essas construtoras aqui não estão bem de acordo com o modelo.
Ah, é, então a gente tem que voltar e atualizar o modelo.
Ou atualizar o código.
Aqui, por exemplo,
Será que procede esse parâmetro aqui?
Se não, vocês retiram do código.
Agora, essa... essa construtora com parâmetros, ela procede?
Procede, porque na classe base tem.
Ah, então, eu vou ter que vir aqui e melhorar meu modelo, tá.
Vir aqui e clicar ali no... no class
e colocar a construtora com parâmetros também.
Uma coisa, isso aqui, também, eu deixei aqui, tá, de... de gatilho
pra lembrar algo no meu discurso que é o seguinte, tá.
Hoje em ambientes modernos, como o Rhapsody, Rational Rose e afins,
ambientes modernos que eu digo em termos de ferramenta CASE
integradas com ambiente de desenvolvimento,
você faz o modelo e ele já atualiza automaticamente no ambiente de programação.
Tipo no Microsoft Visual C++.
Se ele estiverem bem conectadas as duas ferramentas,
e isso é possível, tá, e usual,
Você ter a ferramenta CASE conectada no teu ambiente de desenvolvimento
aí como, por exemplo, como o Microsoft Visual C++.
A hora que você tá com esse ambiente integrado, insisto.
Você consegue então atualizar o teu diagrama
e ele automaticamente vai gerando o código.
Vocês viram antes eu gerar código, lá, a partir da StarUML,
apertando um botão e tal, estimulando a geração de código.
Em ferramentas, top, profissionais,
você já coloca lá
pra ele ir gerando automaticamente à medida que você vai atualizando o modelo.
E quando você, através de um conjunto de astúcias, conecta
a tua ferramenta CASE com o teu ambiente de programação
e você atualiza o código, ele atualiza o modelo aqui também.
Então, se eu estivesse em um ambiente bem integrado,
a hora que eu fosse fazendo as atualizações de código aqui
ele já ia fazer as atualizações no modelo, lá.
Pra vocês terem uma ideia, eu trabalhei num projeto
de um software muito grande de uma dada empresa,
em 1999, e já era assim.
Eu já tinha o Rational Rose lá, que é uma ferramenta CASE
integrado com o então Visual C++ da Microsoft.
E lá em 1999, a gente já mexia no código
atualizava o modelo, mexia no modelo atualizada o código.
Muito legal, uma experiência muito bacana,
que foi assim a minha primeira experiência trabalhando em um projeto grande
realmente utilizando todo esse arcabouço da orientação a objetos.
Inclusive, as implementações eram, dentre outros, em C++.
Na verdade, eram em C++ mas com mais adendos
componentes peculiares lá do C++, ou para o C++.
Mas enfim, o fato é que essa geração de código
a partir de modelo e essa atualização de modelo
a partir de código, na lógica chamada de...
Engenharia Reversa, tá.
Ela é usual.
Inclusive, hoje, já tem toda uma área de pesquisa e até de aplicação chamada MDE.
Model-Driven Engineering.
Engenharia Dirigida ou Guiada por Modelo.
Se você fizer teu modelo bem feitinho,
além do Diagrama de Classes tiver uma série de diagramas de suporte
incluindo, dentre outros, aqui pra cada função-membro
uma espécie de fluxograma, ou seja, um Diagrama de Atividades bem detalhado.
Você consegue consegue gerar boa parte do código
não só estático, mas também do código dinâmico, ou seja,
dos algoritmos que animam, lá, os métodos, tá.
Mas isso é pra vocês tomarem ciência.
Muito embora exista essa geração de código a partir do modelo,
exista mesmo a engenharia reversa que atualiza modelo a partir de código, tá.
Nesse estudo que a gente tá fazendo, em particular,
eu pediria pra vocês não ficarem gerando códigos.
e muito menos fazerem engenharia reversa.
Eu gostaria que vocês fizessem os modelos
e gerassem os códigos na mão,
pra criarem fluência tanto na linguagem de modelagem
quanto na linguagem de programação.
É muito importante nesse momento que vocês dominem sintaticamente,
dominem os nuances da linguagem de modelagem em questão
e particularmente da linguagem de programação em questão.
Depois que vocês tiverem fluentes, daí, a geração de código
pode ocorrer, até deve ocorrer, mas esse é um segundo momento
da vida profissional de vocês, tá.
Nesse momento vocês programam o código efetivamente.
Não gerem código.
Obviamente que você até pode gerar uma ou duas classes só pra
se divertir, pra entender processo,
é um processo interessante, instigante.
Então você pode fazer como experimentação, mas
pro desenvolvimento geral, não o façam.
Ok.
Aqui tá a classe Aluno então, obviamente vai ter o .cpp.
Depois fazer os ajustes que tem que ser feitos, tá.
E aqui nós temos o último slide
que traz essa reflexão sobre o que é uma derivação pública
que é diferente de uma derivação protegida
e diferente de uma derivação privada.
Uma derivação pública
faz com que os elementos protected e public
da classe base continuem como são na classe derivada.
De fato, tá.
Se na classe...
por exemplo, na classe Aluno que herda publicamente de Pessoa,
eu posso criar um Aluno, sei lá eu, Fulano
e fazer Fulano.getNome().
Por quê? Porque o getNome() é público
na classe base Pessoa
e eu estou herdando ele tal qual ele é
lá na classe base.
Por sua vez, se eu fizer uma derivação privada... protegida, perdão acontece o seguinte.
Uma herança protegida faz com que os elementos protected e public
da classe base, sejam todos protected na classe derivada.
Se eu derivasse Aluno de maneira protegida em relação a Professor,
eu não poderia mais fazer Aluno "ponto"...
perdão, criar uma aluno lá, Fulano.
Fulano do tipo Aluno, depois fazer Fulano.getNome().
Porque agora no âmbito do Aluno, o getNome() passou a ser protegido.
Ele pode ser herdado pra classes derivadas,
mas não pode ser utilizados a partir de objetos de Aluno.
E na mesma lógica, ainda mais restritivo, naturalmente.
Uma herança privada faz com que os elementos protected e public
da classe base sejam todos private, privados, né,
na classe derivada.
Então, por exemplo, se eu fizesse Aluno
agora sim, derivado privadamente de Pessoa,
em termos do Aluno, o getNome() seria
um método privado
que não pode ser herdado por outras classes
eventualmente derivadas de aluno e tampouco ser utilizado
diretamente pelos objetos de Aluno
no tocante a chamadas externas.
Dito de outra forma,
se eu fizesse Aluno derivado privadamente de Pessoa
e pegasse lá um Fulano do tipo Aluno,
eu não poderia fazer Fulano.getNome().
O getNome(), por exemplo, passou a ser privado, no âmbito de Aluno.
Bom, pessoal, com isso a gente encerra
essa... esse overview sobre herança, tá.
Uma última observação
é que existe a possibilidade de herança múltipla.
Por exemplo, você tem uma classe derivada
que derivada de duas classes bases,
Deixa eu ver se eu consigo pensar em um exemplo rápido aqui.
Sei lá eu, eu tenho o ornitorrinco, lá.
Classe de ornitorrinco que é derivado de ovíparo e de mamífero.
Então, isso é possível em C++.
Esse é um assunto um pouco mais delicado.
Então eu vou trabalhar esse assunto de herança múltipla
nos... nas apresentações pra frente, tá, nas exposições pra frente.
Herança múltipla é delicada,
e tem uma situação que ela é mais delicada ainda que é o losango ou diamante da morte
Aonde você tem uma classe Alfa que é derivada de Beta e Gama
e Beta e Gama é derivado, sei lá eu, ambas derivadas de Teta.
Então, você forma, na verdade, um losango, né
ou um diamante, tá,
que é uma situação bastante perigosa, peculiar, que a gente vai discutir na sequência.
Tô só levantando o alerta,
porque as vezes o aluno mais interessado resolve estudar um pouco de herança mais
profundamente nos livros que eu indiquei, tá.
Já pra ele levantar o flag, levantar aí as bandeiras de aviso.
No tocante a herança múltipla e particularmente na situação
que você faz um losango, ou um diamante, tá,
que tem uma série de peculiaridades a serem discutidas na sequência.
Bom, pessoal, por essa exposição seria isso.
Nos vemos na próxima exposição.
Até breve e bons estudos.