Linguagens e Ambientes de Programação (2022/2023)
Prática 11
Programação orientada pelos objetos em JavaScript usando classes. Exercícios 51 e 52.
Nota: Os exercícios da aula de hoje destinam-se a ser executados na consola. Nos laboratórios está instalado o JavaScript Node.js, que se invoca usando o comando "nodejs".
Guião para usar a linguagem JavaScript na consola
- Usar um editor de texto qualquer para escrever um ficheiro "Test.js". Gravar.
- Agora, para correr o programa, dar na consola o comando: "nodejs Test.js".
Guião para usar a linguagem JavaScript dentro do Eclipse
- Ativar Eclipse, escrevendo "eclipse" numa consola.
- Window > Open Perspective... mudar perspetiva para JavaScript.
- File > New > JavaScript Project. Escrever "Test" e fazer "Finish". O projeto foi criado.
- File > New > JavaScriptSource File. Dar o nome "Test" e será automaticamente criado o ficheiro "Test.js".
- Escrever o programa no ficheiro "Test.js" e fazer Ctrl-S (save) para gravar.
- Para correr, basta clicar na seta branca dentro da bola verde. O output de todas as chamadas de console.log aparece na consola do Eclipse.
Instalação: Já está instalado nos laboratórios. Para instalar no seu computador pessoal, primeiro veja se o nodejs está instalado. Se não estiver, dê o comando sudo apt install nodejs. Depois use o comando do Eclipse "Help>Install New Software...". Na caixa "Work with:" clique na seta que aponta para baixo e escolha "2018-12 - http://download.eclipse.org/releases/2018-12", ou algo de equivalente. Depois escolha para instalar apenas "Programing Languages/JavaScript Development Tools".
51 - Este é um problema de organização duma hierarquia de classes. É para ser programado em JavaScript, mas imitando as classes do Java, como se explicou na teórica 21. A ideia é usar o suporte para classes que foi introduzido em 2015 no padrão ECMAScript 6.
Resolva o problema usando como orientação os dois exemplos finais da aula teórica 21.
Considere o problema da representação de sucessões numéricas em JavaScript. Vamos restringir-nos a três tipos de sucessões: aritméticas, geométricas e constantes.
- Sucessão aritmética: Caracteriza-se por um primeiro elemento a0 e por um incremento fixo inc. Os elementos da sucessão são gerados usando a equação ai = ai-1+inc.
- Sucessão geométrica: Caracteriza-se por um primeiro elemento a0 e por uma base fixa mult. Os elementos da sucessão são gerados usando a equação ai=ai-1*mult.
- Sucessão constante: Caracteriza-se pelo primeiro elemento a0, apenas. Os elementos da sucessão constante são todos iguais ao primeiro, i.e. ai=a0.
O objetivo é que cada objeto succ que represente uma sucessão consiga gerar os valores dessa sucessão através da invocação repetida de succ.next(). Na nossa representação, as sucessões devem portanto funcionar como iteradores que se lembram da posição corrente em que vão. Atenção: não guarde os valores gerados internamente num array - isso seria desperdiçar memória inutilmente.
Cada tipo de sucessão deverá ser representado por uma classe distinta. Os objetos criados a partir dessas classes (usando a operação new), representarão sucessões concretas. As três classes devem ter a seguinte funcionalidade comum:
- first() -- Faz reset da sucessão (isto é, coloca-a no início) e retorna o primeiro elemento a0.
- curr() -- Retorna o elemento corrente sem fazer avançar a sucessão.
- next() -- Faz avançar a sucessão e retorna o novo elemento corrente.
- at(i) -- Retorna o i-ésimo elemento da sucessão, isto é ai. Entretanto o elemento corrente passa a ser o i-ésimo elemento da sucessão.
- print(n) -- Escreve os n primeiros elementos da sucessão. Entretanto, o elemento corrente passa a ser o n-ésimo elemento da sucessão. (Para escrever um inteiro, use a função do Node.js "console.log".)
Resolva este problema tendo em mente os seguintes objetivos:
- Minimização do código.
- Extensibilidade do sistema.
Não se preocupe com a eficiência.
Antes de programar, desenhe num papel um diagrama que ilustre a relação entre as classes que vai definir, e ainda quais são as variáveis e os métodos de instância de cada uma delas. Para representar uma classe abstrata, use um círculo. Para representar uma classe concreta, use um retângulo.
O seu programa final vai ser um ficheiro contendo a definição de quatro classes. Para testar o programa, convém gerar algum output. Acrescente no final, por exemplo, a seguinte linha de código:
(new Geom(2,3)).print(20);
[Sugestões: 1. Defina uma classe abstrata e fatorize nela o máximo de código. 2. Note que os métodos "at" e "print" podem ser habilidosamente definidos à custa dos métodos "first" e "next".]
52 - Para provar que o sistema criado no problema anterior é realmente extensível, pedimos-lhe que o amplie com duas novas classes, representando dois novos tipos de sucessão:
- Sucessão aritmética otimizada: Sucessão aritmética em que a operação "at" é muito eficiente. [Por vezes define-se uma classe, só para se tornarem mais eficientes determinadas operações. É o caso.]
- Sucessão composta soma: Caracteriza-se por duas sucessões a e b. A sucessão soma define-se pela equação ci=ai+bi.
53 - Adicione ainda mais três tipos de sucessão ao sistema:
- Sucessão composta alternante: Caracteriza-se por duas sucessões a e b. Os elementos da sucessão alternante são gerados pela seguinte ordem: a0, b0, a1, b1, ..., ai, bi, ...
- Sucessão filtro: Caracteriza-se por uma sucessão a e por um número inteiro filtro. Os elementos da sucessão filtro são, pela mesma ordem, os elementos da sucessão que são múltiplos de filtro.
- Sucessão de Fibonnaci: Caracteriza-se pelos dois primeiros elementos a0 e a1. Os elementos da sucessão são gerados usando a equação ai=ai-1+ai-2.
Vídeos antigos
Estes vídeos poderão estar um pouco desatualizados, pois foram feitos no contexto duma edição anterior do LAP. Contudo, partes dos vídeos poderão continuar a ter alguma utilidade.
Nota: Esta aula prática foi gravada no ano letivo passado de 2019/20, com a designação de aula prática 12.
(lap prática 11 parte2)