No olviden completar todos los comentarios de documentación faltantes. Y si ven alguna pre/poscondición que falte, agreguenla.
Asegurensé de que el proyecto funcione correctamente con el proyecto Gradle presente en el repositorio mismo.
En el siguiente diagrama hay un par de cuestiones de notación para tener en cuenta:
- + es publico (
public
) - # es protegido (
protected
) - - es privado (
private
)
Las letras en la fila del nombre de la clase tambien tienen su significado.
- (A) Abstracto (
abstract class
) - (C) Clase (
class
)
Finalmente, los métodos abstractos, se ven en 'italica' en el diagrama.
Siguiendo lo que estuvimos viendo en clases como ejemplo. Su trabajo ahora es completar todo lo que falta y algunas operaciones adicionales.
Implementen las clases siguiendo el siguiente diagrama:
Si se les ocurren más operaciones, ¡bienvenidas sean!
Un detalle sobre el tipo de valores
, esto es un
ArrayList
que está en el paquete java.util.ArrayList
Es una forma más fácil (que los arreglo) de guardar conjuntos
de cosas, en este caso, de Operacion
.
Contiene un poco de sintaxis extra que no vimos puntualmente hoy
La sintaxis general agrega entre <
y >
el tipo de lo
que será almacenado.
ArrayList<tipo> variable = new ArrayList<tipo>();
Y un ejemplo concreto para guardar números enteros
(solo es posible guardar Objetos, por lo que es necesario usar
los "wrappers" en lugar de int
directamente)
ArrayList<Integer> conjuntoNumeros = new ArrayList<Integer>();
Y otro, para guardar instancias de Operacion
ArrayList<Operacion> valores = new ArrayList<Operacion>();
Un detalle importante, el ArrayList valores
no contiene
nada aún, para eso, tiene que hacer algo como valores.add(op1)
Pero para más detalles sobre lo que pueden hacer, consulten con su manual: ArrayList
Siempre pueden usar un array
comun:
Operacion[] valore = new Operacion[10];
Pero estarían limitados a una cantidad fija de Operacion
.
Mientras que con el ArrayList
, cuantos hay, no importa.
Creen un paquete para la calculadora, en la cual estarán las clases Operación, Numero y la excepción raíz.
Asimismo, creen un paquete para agrupar los tipos de operaciones, uno para las unarias, otro para binarias y uno para las multiples.
Normalmente, empleamos la notación "infija", en la cual el operador va en el medio de los operandos. En esta notación, es necesario definir la precedencia de los operandos para saber que par de operaciones resolver primero.
La notación polaca es una forma de construir operaciones binarias sin la utilización de paréntesis, solo es necesario separar los operandos entre sí con un espacio. Esta solo funciona con operaciones binarias como está definida.
Un ejemplo simple de esta notación para una suma: + 2 3
es 2 + 3
.
El resultado esperado con la calculadora sería algo como
Numero operandoUno = new Numero(2);
Numero operandoDos = new Numero(3);
Operacion resultado = new Suma(operandoUno, operandoDos);
Y un ejemplo un poco menos simple, * + 2 6 5
es (2+6)*5
.
Numero dos = new Numero(2);
Numero seis = new Numero(6);
Numero operandoIntermedio = new Suma(dos, seis);
Numero cinco = new Numero(5);
Operacion resultado = new Multiplicacion(operandoIntermedio, cinco)
Finalmente, otro ejemplo sin procesar con las expresiones que pueden encontrarse.
Su misión, si desea aceptarla, es construir un programa que utilizando un Stack
, procese un String
con una expresión
matemática y pueda obtener su resultado.
Primero que procese String
s que contengan expresiones binarias, y después encaren el resto. Como siempre, observen
la separación de la entrada y salida.
El método a implementar sería algo como:
public Operacion desdeCadena(String expresiones) throws CalculadoraExcepcion;
Este método puede estar en Operación
y probablemente sea un método estático.
Pueden modificar todas las clases y métodos de la consigna original para este ejercicio extra. Algo para agregar, es
un método en Operacion
que sea aCadenaPolaca()
para verificar que el método implementado funcione correctamente.
(Si la estructura resultante es la misma, entonces la implementación es correcta.)
Siguiendo el primer ejemplo
Numero operandoUno = new Numero(2);
Numero operandoDos = new Numero(3);
Operacion resultado = new Suma(operandoUno, operandoDos);
Operacion interpretada = Calculadora.desdeCadena(resultado.aCadenaPolaca());
En donde resultado
e interpretada
deben ser la misma estructura y dar el mismo resultado.
(Es una oportunidad interesante para implementar equals
)
A pesar de que la notación no está pensada para operandos multiples o unarios, es posible introducir paréntesis para
saber cuáles son los operandos que pertenecen a una OperaciónMultiple.
Por ejemplo:
SUMA(3 5 6 7 + 3 3)
es SUMA(3, 5, 6, 7, (3 + 3))
.