Temas:
Solución de la tarea de la clase anterior
(Revise el ejercicio de la clase anterior.)
Los objetos de la clase Adivino se representarán mediante 2 variables de instancia:
Observaciones:
class Adivino {
int intentos;
int min;
Adivino(int min, int max) {
this.min= min; // ¡se ignora max!
intentos= 0;
}
int jugar() {
this.intentos= this.intentos+1;
return this.min;
}
int mayor(int n) {
this.min= n+1;
}
int menor(int n) {
}
int intentos() {
return this.intentos;
}
}
Estrategia inteligente
La estrategia implementada para adivinar el número no es muy inteligente y probablemente aburrirá rápidamente a cualquier jugador antes que termine el juego.
A continuación escribiremos una nueva versión de la clase Adivino que, por supuesto, no requiere que se modifique el programa que dialoga con el usuario. Esta clase adivinará en no más de 10 intentos el número del usuario.
Las características de la clase son las siguientes:
class Adivino {
int intentos;
int min;
int max;
Adivino(int min, int max) {
this.min= min;
this.max= max; // Ahora *si* se considera max.
intentos= 0;
}
int jugar() {
this.intentos= this.intentos+1;
return (this.min+this.max)/2;
}
int mayor(int n) {
this.min= n+1;
}
int menor(int n) {
this.max= n-1;
}
int intentos() {
return this.intentos;
}
}
Al contrario, las clases inmutables no poseen ningún método que haga variar su estado interno. En este tipo de clases, si se invoca dos veces un mismo método con los mismos argumentos, el método siempre retornará el mismo valor. También se dice que los métodos de una clase inmutable no producen efectos laterales en sus objetos.
Ejemplo: los hiper ints
La clase HiperInt permite representar números enteros positivos de hasta 1000 dígitos. Esta clase posee los siguientes métodos:
| Ejemplo | Significado | Declaración |
|---|---|---|
| HiperInt hi= new HiperInt(1023); | Construye un HiperInt | HiperInt(int n) |
| HiperInt hk= hi.suma(hj); | entrega la suma de hi y hj | HiperInt suma(HiperInt h) |
| HiperInt hk= hi.producto(hj); | entrega el producto de hi y hj | HiperInt producto(HiperInt h) |
| if (hi.comparar(hj)==0) ... | comparar hi con hj (-1, 0, 1) | int comparar(HiperInt h) |
| println(hi.toString()) | entrega el HiperInt como string | String toString() |
Esta clase se puede usar para calcular el factorial de números tan grandes como 500 en forma exacta:
Definición de la clase HiperInt
print("n ? ");
int n= readInt();
int i= 1;
HiperInt fact= new HiperInt(1);
while (i<=n) {
fact= fact.producto(new HiperInt(i));
i= i+1;
}
println(fact.toString());
La idea es representar los dígitos de un HiperInt en un arreglo de enteros. El dígito menos significativo en el índice 0, el segundo dígito menos significativo en el índice 1 y así en adelante. Por ejemplo, el número 1075 será almacenado en el siguiente arreglo:

Observación:
class HiperInt {
int[] digitos;
HiperInt(int k) {
this.digitos= new int[1000]; // Inicialmente todos en 0
int i= 0;
while (k>0) {
this.digitos[i]= k%10;
k= k/10;
}
}
HiperInt suma(HiperInt hk) {
HiperInt res= new HiperInt(0);
int i= 0;
int acarreo= 0;
while (i<1000) {
res.digitos[i]= this.digitos[i]+hk.digitos[i]+acarreo; // (*)
i= i+1;
}
// Si acarreo!=0 hubo desborde, pero no haremos nada
return res;
}
// Resto de los métodos: tarea
}
Como regla general, las clases inmutables se pueden distinguir de las clases mutables, mirando qué retornan sus métodos. Las clases que tienen algún método void son mutables. En cambio, cuando los métodos siempre retornan un valor, es altamente probable que se trate de una clase inmutable.
Por ejemplo la clase Fecha vista anteriormente es inmutable, mientras que la clase Tortuga es mutable, puesto que tiene métodos void. La clase TextReader no tiene métodos void, sin embargo es mutable porque las distintas invocaciones de readInt entregan enteros distintos.
Tarea:
Complete la clase HiperInt definiendo primero el método comparar y luego el método producto.