Clases A principio del semestre dijimos que veríamos:
Clase Principal { Método Principal () {....} Método1() {....} Método2() {....} :
}
Clase1 { Atributos Clase1 Constructores Clase1 Métodos Clase1
} Clase2 { Atributos Clase2 Constructores Clase2 Métodos Clase2
} Etc... 1
Clases Hasta ahora hemos visto clases que:
• Contienen el método principal (main) el cual es el que se ejecuta cuando corremos un programa.
• A la vez esta clase que contiene el método principal puede contener otros métodos aparte del principal (main).
• También hemos visto clases que contienen sólo
métodos donde ninguno es el principal, como la clase SimilitudVectores de la Tarea 1, la clase In y la clase Util. Estos métodos están a nuestra disposición para cuando necesitemos usarlos. 2
Clases También dijimos que para llamar métodos que
están en otra clase debemos especificar el nombre de la clase. Podemos tener varias clases en un mismo
programa, como lo hicimos en la Tarea 1. Sin embargo, si tenemos varias clases en un mismo programa sólo una debe contener el método principal. El archivo .java se debe llamar igual que la
clase que contiene el método principal. 3
Clases Ahora veremos Clases que nos permitirán
crear Objetos. Hasta ahora hemos usado dos tipos de Objetos: los Strings y los Arreglos. Ahora crearemos nuestras propias Clases que
nos permitirán crear los Objetos que nosotros queramos. En este tipo de clases tenemos:
• Una lista de atributos. • Una lista de métodos.
4
Clases Por ejemplo, supongamos que queremos
hacer un programa que nos permita manejar números complejos. Los números complejos tienen una parte imaginaria y una parte real, y si por ejemplo queremos sumar dos números complejos debemos sumar ambas partes por separado. En Java no existe una Clase para manejar números complejos. ¿Qué podemos hacer? La crearemos nosotros 5
Clases Cuando creamos una clase que nos permitirá crear
objetos en general tendremos: class NombreClase { atributo1 atributo2 etc.
métodos constructores() métodos setters() método getters()
Lista de atributos
Lista de métodos
Otros métodos } 6
Clases Lista de atributos
La lista de atributos se refiere a las características de los objetos que crearemos. Por ejemplo, los números complejos se caracterizan por tener una parte real y una parte imaginaria. class Complejo { double real; double imaginaria; métodos constructores() métodos setters() método getters() Otros métodos }
7
Clases Métodos Constructores
• Cuando creemos un objeto de la clase Complejo
debemos inicializar los atributos de este objeto. Para esto necesitamos un constructor. El nombre del método constructor es el mismo que el de la clase.
• Este método tiene una lista de parámetros que, en general, se refiere a los atributos de la clase.
• Por ejemplo, en este caso tendremos: public Complejo (double r, double i) { real=r; imaginaria=i; } 8
Clases Hasta ahora tenemos: class Complejo { double real; double imaginaria; public Complejo (double r, double i) { real=r; imaginaria=i; }
Lista de atributos
Método constructor
}
9
Clases Con lo que tenemos hasta ahora ya podemos
crear un Objeto de la clase Complejo. Ejemplo de cómo crear un objeto de la clase Complejo (esto podría ser una instrucción en el main): Complejo c= new Complejo(2,3); Nombre de la clase
Nombre del objeto
Llamada al método constructor 10
Clases Complejo c= new Complejo(2,3); es equivalente a: Complejo c; c= new Complejo(2,3); Veamos que pasa cuando creamos un Objeto
de la clase Complejo.
11
Clases Complejo c;
Creamos una variable c que es una referencia a un Objeto de tipo Complejo, pero todavía no hemos creado al Objeto. c
Como lo hemos dicho antes, esto es la regla cuando
hablamos de objetos, no así cuando creamos variables de tipo primitivo. Podemos recordar que cuando creábamos arreglos también decíamos que la variable no guardaba el arreglo sino que era una referencia a un arreglo 12
Clases c= new Complejo(2,3);
Ahora recién hemos creado un objeto de tipo Complejo. Lo podemos ver como que recién tenemos un espacio de memoria (no lo tomen literalmente) donde se guarda nuestro objeto recién creado. c real= 2.0 imaginaria=3. 0
Este es nuestro Objeto de tipo Complejo
Es decir en un espacio de memoria se guarda c que es una referencia a un objeto de tipo Complejo y en otra se guarda el objeto al cual c hace referencia 13
Clases Para darle valores a los atributos de este
objeto usamos el método constructor Complejo que dice que el primer argumento se le asignará al atributo real y el segundo al atributo imaginaria. c= new Complejo(2,3); public Complejo(double r, double i) { real= r; imaginaria= i; } 14
Clases class Ejemplo { public static void main(String[] args) { Complejo c1= new Complejo(2,3); Complejo c2; c2= new Complejo(3.5,4); c1.real= 4; c1.imaginaria= c1.imaginaria*2; System.out.println(c1.real+ " + "+ c1.imaginaria+"i"); System.out.println(c2.real+ " + "+ c2.imaginaria+"i"); } } class Complejo { double real; double imaginaria; public Complejo(double r, double imag) { real= r; imaginaria= imag; } }
15
Clases Complejo c1= new Complejo(2,3);
Creamos la variable c1 que es una referencia a un Objeto de tipo Complejo. A la vez estoy creando el Objeto y lo estoy inicializando a través del método constructor con los valores 2 y 3 que son la parte real y la parte imaginaria respectivamente. c1 real= 2.0 imaginaria=3. 0 16
Clases Complejo c2;
Creo la variable c2 que es una referencia a un Objeto de tipo Complejo, el cual todavía no he creado.
c2= new Complejo(3.5, 4);
Creo el objeto al que c2 hará referencia y le doy valor a sus atributos a través del método constructor.
c2
c2 real= 3.5 imaginaria=4. 0
17
Clases En resumen hasta ahora tengo dos objetos de la Clase
Complejo.
c1 real= 2.0
c2
imaginaria=3. 0 real= 3.5 imaginaria=4. 0
En general, podemos crear cuantos objetos queramos.
Sin embargo, el hecho de que creemos la clase Complejo no quiere decir que obligatoriamente debemos crear objetos de esa clase.
18
Clases c1.real= 4;
Cambiamos el valor del atributo real de 2.0 a 4.0 del Objeto al cual hace referencia c1
c1 real= 4.0 imaginaria=3. 0
Aquí es importante destacar que:
Podemos tener varios objetos, por lo tanto siempre al referirnos a un atributo debemos especificar de que Objeto estamos hablando, no podemos sólo escribir: real= 4;
19
Clases c1.imaginaria= c1.imaginaria*2;
c1
c1
real= 4.0
real= 4.0
imaginaria=3. 0
imaginaria=6. 0
Cambiamos el valor del atributo imaginaria del Objeto al cual hace referencia c1. 20
Clases System.out.println(c1.real+ " + "+ c1.imaginaria+"i");
System.out.println(c2.real+ " + "+ c2.imaginaria+"i");
Finalmente imprimimos los Objetos recién creados. Aquí es importante destacar que no podemos llegar y
escribir:
System.out.println(c1); Pues esta clase la creamos nosotros y Java no tiene una especificación de que hacer si le decimos que imprima un Objeto creado por nosotros. En este caso, por ejemplo imprime:
Complejo@18a992f
21
Clases En este caso Java imprime un String que
contiene la clase y el espacio de memoria donde se guarda el objeto que estamos tratando de imprimir. Si escribimos:
Complejo c; System.out.print(c); ¿Qué pasará?
22
Clases Hemos creado una variable c que es una
referencia a un objeto de la clase Complejo pero aun no hemos creado el objeto. c
Por lo tanto cuando tratamos de imprimir c
nos sale el siguiente mensaje de error:
The local variable c may not have been initialized
23
Clases El problema es que no le hemos dado a c un
objeto al cual hacer referencia, por lo tanto cuando queramos usar c en este u otros contextos nos va a salir este mensaje de error.
Este mensaje es el mismo que nos salía
cuando queríamos usar una variable de tipo primitivo sin haberla inicializado. Por ejemplo: int numero; while (numero != -1) { ....................... } 24
Clases Sin embargo, en el caso de variables que
hacen referencia, podemos asignarles el valor null. En este caso no hemos creado un objeto pero Java no nos va a reclamar por problemas de inicialización. Por ejemplo podemos tener: Complejo c= null; System.out.print(c); En este caso se imprimiría null y no tendríamos un errorcde compilación.
25
Clases ¿En qué contextos nos sirve asignarle null a una variable? Uno de los contextos es cuando queremos hacer
verificaciones. Por ejemplo, si estamos recorriendo una lista de largo desconocido, sabemos que el último elemento es el que está antes del primer null. O 1
O 2
O 3
O 4
NULL
NULL
NULL
NULL
NULL
NULL
este sería el último
Más adelante, cuando veamos un arreglo de objetos esta
idea nos va a quedar más clara. 26
Clases Veamos nuevamente la clase de los Complejos que
hicimos la clase pasada:
class Complejo { double real; double imaginaria;
Atributos
public Complejo(double r, double imag) { real= r; imaginaria= imag; }
Método Constructor
} 27
Clases En esta clase podríamos no haber creado un
método constructor. En este caso Java provee un constructor por defecto. Este método constructor le da los siguientes valores a los atributos:
• Si son numéricos les da valor 0. • Si son boolean les da valor false. • Si son referencias les da valor null.
La forma de crear un objeto en este caso
sería: Complejo c= new Complejo(); 28
Clases Cuando decimos que un atributo es una
referencia nos referimos a que es una variable que va a hacer referencia a algún objeto. Por ejemplo, uno de los atributos de una clase podría ser un arreglo o un String. Supongamos que tenemos la siguiente clase: class Estudiante { String nombre; int creditos; double promedio; }
29
Clases Como no hemos creado un método constructor Java crea
uno por defecto. Por lo tanto, al escribir: Estudiante e1= new Estudiante(); Creamos e1 que es una variable que hace referencia a un Objeto de la clase Estudiante. El método constructor de Java le asignará null a nombre, 0 a creditos y 0.0 a promedio. e1 nombre creditos= 0 promedio= 0.0 30
Clases Recuerden que Java provee de un método constructor,
sólo si nosotros no creamos uno. Si tenemos la clase: class Complejo { double real; double imaginaria; public Complejo(double r, double imag) { real= r; imaginaria= imag; } }
No podemos escribir: Complejo c= new Complejo(); 31
Clases Podemos tener más de un método constructor en una
clase. Por ejemplo: class Complejo { double real; double imaginaria;
Lista de atributos
public Complejo(double r, double imag) { real= r; imaginaria= imag; }
Primer Constructor
32
Clases public Complejo(double r) { real= r; imaginaria= 0; }
Segundo Constructor
public Complejo() { real= 0; imaginaria= 0; }
Tercer Constructor
} 33
Clases Luego si escribimos: Complejo c1= new Complejo(); Complejo c2= new Complejo(1, 3.5); Complejo c3= new Complejo(1); Hemos creado 3 objetos de la clase Complejo c1
c2
c3
real= 0.0
real= 1.0
real= 1.0
imaginaria= 0.0
imaginaria= 3.5
imaginaria= 0.0 34
Clases Complejo c1= new Complejo();
En este caso Java (el compilador) sabe que hay 3 constructores pero como se está llamando al constructor sin argumentos Java se dirige al método constructor que tiene una lista de parámetros vacía, es decir, el tercer constructor. Complejo c2= new Complejo(1,3.5);
Nuevamente Java sabe que hay 3 constructores pero como se está llamando al constructor con 2 argumentos, Java se dirige al método constructor que tiene una lista de parámetros con dos argumentos, es decir, el primer constructor.
35
Clases Complejo c3= new Complejo(1);
Java sabe que hay 3 constructores pero como se está llamando al constructor con 1 argumento, Java se dirige al método constructor que tiene una lista de parámetros con 1 argumento, es decir, el segundo constructor. El tener más de un método con el mismo nombre se llama sobrecarga de métodos. Si llamamos un método que está sobrecargado Java revisa los encabezados de los métodos. Cuando el encabezado de un método coincide con el llamado se ejecutan las instrucciones de este método. 36
Clases En el encabezado de un método java revisa:
- El nombre (identificador) - Número de parámetros - Tipo de los parámetros Si se llama a un método que está
sobrecargado, Java se dirige al que tenga el mismo nombre, número de parámetros y tipo. Si el tipo no coincide pero es legal hacer una conversión (por ejemplo de int a double), Java se dirige a este método. 37
Clases ¿Qué otro ejemplo de sobrecarga de métodos
hemos visto hasta ahora? IndexOf Hay varias versiones de este método:
int int int int
indexOf( indexOf( indexOf( indexOf(
char ch ) char ch, int fromindex ) String str ) String str, int fromindex)
38
Métodos estáticos y de instancia Existen dos tipos de métodos: métodos de
instancia y métodos estáticos (también llamados métodos de clases). Hasta ahora los métodos creados por nosotros han sido en su mayoría métodos estáticos y por eso en el encabezado incluíamos la palabra static. Los únicos métodos de instancia creados por nosotros hasta ahora han sido los métodos constructores. Sin embargo, hemos usado los métodos de instancia de la clase String.
39
Métodos estáticos y de instancia La diferencia principal es que los métodos de
instancia deben ser llamados por un objeto (de la clase donde se crea el método). Dentro de los métodos de instancia se
necesita hacer uso de los atributos del objeto que llama al método. Los atributos del objeto se necesitan para ser alterados o para sacar alguna información.
40
Métodos de instancia Un ejemplo de un método de instancia que
hemos usado hasta ahora es: charAt A este método lo debe llamar un objeto de la clase String. Por ejemplo: String s= “Hola”; char c= s.charAt(2);
41
Métodos de instancia Los métodos constructores son también
métodos de instancia. Sin embargo son diferentes a todos los otros métodos de instancia por la forma en que se llaman. Complejo c1= new Complejo(2,3);
Aquí estamos llamando al método constructor
42
Métodos de instancia Los métodos de instancia:
• Son métodos creados dentro de una clase y deben ser llamados por objetos de esa clase. • En su encabezado no se incluye la palabra static. • Para llamar a estos métodos escribimos (a excepción de los constructores): <nombre del objeto>.<nombre del método>(parámetros) Por ejemplo: s.charAt(2);
• Dentro del método se hace uso de los atributos del
objeto que lo llama. Como lo llama un objeto no debemos especificar el nombre del objeto para usar sus atributos. Al objeto que llama al método lo llamaremos objeto implícito.
43
Métodos de instancia Escriba un método de instancia para la clase
de los complejos que multiplique por dos los atributos del objeto implícito. public void porDos() { real= real*2; imaginaria= imaginaria*2; }
Cuando hablamos de real e imaginaria, estamos hablando de los atributos del objeto que llamó a este método, a este objeto lo llamamos el objeto implícito. 44
Métodos de instancia Por ejemplo, supongamos que en el main
escribimos: Complejo c1= new Complejo(2,4); Complejo c2= new Complejo(1, 3.5); c2.porDos();
Con las dos primeras instrucciones creamos
dos objetos (instancias) de la clase Complejo. c1
c2
real= 2.0 imaginaria= 4.0
real= 1.0 imaginaria= 3.5
45
Métodos de instancia Luego cuando escribimos:
c2.porDos(); Lo que estamos haciendo es llamar al método porDos con el objeto c2, es decir, c2 es el objeto implícito. Las instrucciones de este método indican que se deben alterar los atributos del objeto que lo llamó. En este caso los atributos del objeto se multiplican por dos. Cuando en el método digo “real” estoy hablando de la parte real de c2 pues es el objeto que lo llamó. Si luego en otra instrucción llamamos al método con c1, entonces c1 será esta vez el
46
Métodos de instancia Por lo tanto, el resultado de estas tres
instrucciones será: c1
c2
real= 2.0 imaginaria= 4.0
real= 2.0 imaginaria= 7.0
47
Métodos de Instancia Escriba un método de instancia para la clase de los
complejos que reciba num1 y num2 (enteros) y que retorne un complejo cuya parte real es igual a la parte real del objeto implícito por num1 y la parte imaginaria es igual a la parte imaginaria del objeto implícito por num2. El objeto implícito no es alterado. public Complejo otro(int num1, int num2) { Complejo c= new Complejo(); c.real= real*num1; c.imaginaria= imaginaria*num2; return c; } 48
Métodos de Instancia De este ejemplo podemos destacar que:
• Podemos crear objetos no sólo en el main sino que también en otros métodos, en este caso fue un método de instancia.
• Un método puede retornar objetos, en este caso retorna un Complejo. Por lo tanto, para llamarlo podemos decir por ejemplo: Complejo c3= c1.otro(2,3);
• Cuando decimos
real*num1 no alteramos el valor del atributo real del objeto implícito, sino que simplemente estamos haciendo uso de su valor. Si queremos cambiarlo debemos decir: real= .....; 49
Métodos de instancia Escriba un método de instancia para la clase de los
complejos que compare si el contenido de dos objetos de la clase Complejo es igual. Los dos objetos son el implícito más otro que se recibe como argumento. Llame a este método equals. Si el contenido es igual debe retornar true, en caso contrario false. public boolean equals(Complejo c) { if(c.real== real && c.imaginaria== imaginaria) return true; else return false; }
50
Métodos de instancia De este ejemplo podemos destacar que:
• No podemos usar == para comparar el contenido de dos objetos, pues esto devuelve true sólo si hablamos del mismo objeto. Por este motivo, muchas veces para las clases que creamos, se crea el método equals.
• Un método puede recibir objetos, en este caso recibe un Complejo.
• Para llamarlo podemos decir por ejemplo: boolean a= c1.equals(c2); objeto implícito 51
Métodos de instancia Escriba un método de instancia que sume dos
complejos, el implícito más uno que recibe como argumento y retorne un objeto de la clase Complejo que sea la suma del objeto implícito más el objeto que se usa como argumento. El método se debe llamar suma. public Complejo suma(Complejo c) { Complejo a= new Complejo(); a.real= c.real + real; a.imaginaria= c.imaginaria + imaginaria; return a; } 52
Métodos de instancia Para llamarlo podemos decir por ejemplo:
Complejo c3= c1.suma(c2); Este es el objeto que llama al método, y por lo tanto es el objeto implícito
53
Métodos de instancia Escriba un método de instancia que retorne el
valor absoluto o magnitud del objeto implícito.
public double magnitud() { double magnitud= Math.sqrt(real*real + imaginaria*imaginaria); return magnitud; }
54
Métodos de instancia Escriba un método que retorne un Complejo que sea el
conjugado del objeto implícito.
public Complejo conjugado() { Complejo c= new Complejo(); c.real= real; c.imaginaria= - imaginaria; return c; } 55
Métodos de instancia Si todavía los confunde usar los nombres de los
atributos en los métodos de instancia sin indicar explícitamente a que objeto se refieren pueden usar this, donde this se refiere al objeto implícito. Por ejemplo, el método anterior lo podemos cambiar por: public Complejo suma(Complejo c) { Complejo a= new Complejo(); a.real= c.real + this.real; a.imaginaria= c.imaginaria + this.imaginaria;
return a; } 56
Métodos de instancia this también se usa para evitar
ambigüedades. Por ejemplo, si una variable dentro de un método de instancia se llama igual que un atributo debo decir this.<nombre del atributo> para indicar que me refiero al atributo y no a la variable.
57
Métodos de instancia class Cuadrado { double lado; public Cuadrado(double ld) { lado = ld; } public double area() { return lado*lado; } }
58
Métodos de instancia Explique paso a paso: class Ejemplo { public static void main(String[] args) { Cuadrado c1= new Cuadrado(9); Cuadrado c2= new Cuadrado(3.5); Cuadrado c3; c3= c1; double a; a= c2.area(); System.out.println(a);
59
Métodos de instancia boolean b; b= c1==c2; System.out.println(b); c1.lado= 3; c2.lado= 3; b= c1==c2; System.out.println(b);
60
Métodos de instancia b= c3==c1; System.out.println(b); c1.lado= 4; System.out.println(c3.lado); System.out.println(c1.area()); c3=c1; c2=c3; System.out.println(c1.lado+" "+c2.lado+" "+c3.lado+" "); System.out.println(c1+" "+c2+" "+c3+" "); } }
61
Ejemplo de Clases y Objetos Queremos almacenar datos de una cuenta
bancaria. Clase: Cuenta.
• Atributos: rut, saldo. • Métodos: Cuenta (constructor), giro, deposito, transferir.
62
Ejemplo de Clases y Objetos class Cuenta { String rut; int saldo; public Cuenta (String id, int monto) { rut = id; if (monto > 0) saldo = monto; else saldo = 0; }
63
Ejemplo de Clases y Objetos public boolean giro(int monto) { if (saldo >= monto) { saldo = saldo - monto; return true; } else return false; }
public boolean deposito(int monto) { if (monto >= 0) { saldo = saldo + monto; return true; } else return false; }
64
Ejemplo de Clases y Objetos public boolean transferir(int monto, Cuenta cta) { if (monto <= 0 || monto > saldo) return false; else { saldo = saldo - monto; cta.deposito(monto); return true; } } }
65
Ejemplo de Clases y Objetos class Ejemplo { public static void main(String[] args) { Cuenta cta1 = new Cuenta("3.205.679-2", 40000); boolean resultado; resultado = cta1.deposito(5000); if (resultado) { System.out.println("Deposito de 5000 ha sido realizado"); System.out.println("Nuevo saldo: " + cta1.saldo); } else System.out.println("Deposito de 5000 no pudo realizarse");
66
Ejemplo de Clases y Objetos resultado = cta1.giro(60000); if (resultado) { System.out.println("Giro de 60000 ha sido realizado"); System.out.println("Nuevo saldo: " + cta1.saldo); } else System.out.println("Giro de 60000 no pudo realizarse");
67
Ejemplo de Clases y Objetos resultado = cta1.giro(30000); if (resultado) { System.out.println("Giro de 30000 ha sido realizado"); System.out.println("Nuevo saldo: " + cta1.saldo); } else System.out.println("Giro de 30000 no pudo realizarse");
68
Ejemplo de Clases y Objetos Cuenta cta2 = new Cuenta("34.675.817-3", 2000000); resultado = cta1.transferir(30000, cta2); if (resultado) System.out.println( "Transferencia realizada\n" + "Saldo cuenta origen " + cta1.rut + " : " + cta1.saldo + "\n" + "Saldo cuenta destino " + cta2.rut + " : " + cta2.saldo); else System.out.println( "Transferencia no realizada"); } }
69
Métodos Estáticos Acabamos de revisar lo que son los métodos
de instancia. Antes de eso sólo habíamos hecho métodos estáticos.
Un método es estático si se incluye en el
encabezado la palabra static.
Estos métodos también se llaman métodos de
clase.
Si es estático no necesitamos llamarlo con un
objeto de la clase donde se crea el método.
70
Métodos Estáticos En una clase que nos permite crear objetos,
no sólo podemos que tener métodos de instancia, también podemos tener métodos estáticos. A veces resulta más natural implementar un método como estático que como de instancia. Por ejemplo, en la clase Complejo, implementamos el método suma que retornaba un complejo que era la suma del objeto implícito más uno que recibía como argumento. En este caso, resulta más natural implementar este método como un método estático. Por lo tanto debería recibir dos objetos de la clase Complejo como argumento.
71
Métodos Estáticos Ejemplo del método suma como método de
instancia:
public Complejo suma(Complejo c) { Complejo a= new Complejo(); a.real= c.real + real; a.imaginaria= c.imaginaria + imaginaria; return a; }
72
Métodos Estáticos Ejemplo del método suma como método estático: public static Complejo suma(Complejo c1, Complejo c2) { Complejo a= new Complejo(); a.real= c1.real + c2.real; a.imaginaria= c1.imaginaria + c2.imaginaria; return a; }
Como es un método estático, aunque este método esté dentro de la clase Complejo no se le llama con un objeto de esta clase. Por lo tanto no existe un objeto implícito, todos los objetos son explícitos, en este caso c1 y c2. 73
Métodos Estáticos Una forma de llamar a este método sería por
ejemplo: c1= Complejo.suma(c2,c3); Donde c1, c2 y c3 con objetos de la clase Complejo. Aquí estamos asumiendo que el método main
no está en la clase Complejo, por eso debemos incluir además el nombre de la clase al llamar al método.
74
Métodos Estáticos Para llamar a un método estático se usan las
mismas reglas que conocíamos anteriormente:
• Si el método está en la misma clase desde donde se llama al método sólo debemos incluir el nombre del método. • Si el método está en otra clase debemos escribir: < nombre de la clase>. <nombre del método>
Por ejemplo, si quisiéramos llamar al método suma desde el main (y el main no está en la clase Complejo) deberíamos escribir: Nombre del método Nombre de clase c1=laComplejo.suma(c2,c3); 75
Resumen Hasta ahora en clases, hemos creado la clase
Complejo. Esta se ve así:
class Complejo { double real; double imaginaria;
2 atributos
public Complejo(double r, double imag) {...} public Complejo(double r) {...} public Complejo() {...} public public public public public
3 constructores
void porDos() {...} Complejo otro(int num1, int num2) {...} 5 boolean equals(Complejo c) {...} Complejo conjugado() {...} double magnitud() {...}
métodos de instancia
1 public static Complejo suma(Complejo c1, Complejo c2) {...}
método estático
} 76
Resumen Podemos usar esta clase creando objetos de ella y
usando sus métodos. Esto lo podemos hacer en el método principal, el main. El main puede estar dentro de la clase igual que los otros métodos: class Complejo { double real; double imaginaria; . . . public static void main (String[] args) { } } 77
Resumen Pero no resulta muy natural tener una clase con el
main, que además nos permita crear objetos, por lo que siempre la tendremos en una clase separada: class Ejemplo { public static void main (String[] args) { ................. } } class Complejo { .......... }
78
Resumen Como le hemos dicho antes, podemos incluir
ambas clases en distintos archivos (diferentes códigos) o las podemos tener en un sólo archivo. Si las tenemos en un solo archivo .java este
se debe llamar como la clase que contiene el método principal. En el ejemplo anterior, el archivo se debe llamar Ejemplo.java
79
Resumen Para llamar a un método desde otro método
lo importante es saber: - En que clase esta el método - Si el método es de instancia o estático.
2. Misma clase/estático
Si el método está en la misma clase que el método que lo llama y es estático no debemos especificar el nombre de la clase. Por lo tanto sólo escribimos: <nombre del método> 80
Resumen Por ejemplo, supongamos que tenemos: class Ejemplo { public static void main(String[] args) { ......... double a= factorial(13); }
Dos métodos en la misma clase
public static double factorial(int numero) { ........... Método estático return fact; } }
81
Resumen 1. Distintas clases/estático
Si los métodos están en distintas clases debemos especificar el nombre de la clase. Por lo tanto, para llamar a un método estático que está en otra clase escribimos: <nombre de la clase>. <nombre del método>
82
Resumen Por ejemplo, supongamos que tenemos: class Ejemplo { public static void main(String[] args) { ......... double a= Otra.factorial(13); } }
Dos métodos en distintas clases
class Otra { public static double factorial(int numero) { ........... Método estático return fact; } } 83
Resumen 1. Misma clase/instancia
Distinta clase/instancia
En ambos casos: - Se llama al método con un objeto. - No se especifica el nombre de la clase. Por lo tanto para llamar a un método de instancia siempre escribimos: <nombre del objeto>.<nombre del método> Por ejemplo, el siguiente código podría estar en un método que está en otra clase o en un método que está dentro de la clase Complejo: Complejo c= new Complejo(3,4); int a= c.magnitud(); nombre del objeto 84
Ocultamiento de información Hasta ahora, en todos los métodos que hemos
creado incluimos la palabra public. La palabra public tiene relación con el acceso que tenemos a los métodos desde otras clases o paquetes. Hasta ahora hemos hecho programas muy cortos y por lo tanto no teníamos que preocuparnos mucho por como agrupar y organizar nuestros archivos. Sin embargo, si quisiéramos hacer programas más grandes podríamos agrupar las clases en paquetes. 85
Ocultamiento de información Un paquete es una conjunto de clases. Una clase a su vez es un conjunto de
métodos. Cuando ustedes guardan un archivo .java,
como no especifican un paquete (no crean un paquete), este archivo se guarda en el paquete por defecto, el cual es el directorio donde se creó el programa (depende también de la plataforma). 86
Ocultamiento de información La palabra public la podemos usar al inicio
de una clase, método o atributo.
Por ejemplo: public class Complejo { public double real; public double imaginaria; public Complejo(double r, double i) { ...... } } 87
Ocultamiento de información Si decimos que un método es público decimos que
puede ser llamado desde cualquier otro método. Es decir, el método que lo llama puede estar en cualquier clase, la cual a su vez puede estar en cualquier paquete.
El main siempre debe ser público. Si en un método reemplazamos la palabra public por
private, podremos acceder a este método sólo desde la clase donde está el método. Es decir, sólo métodos de la misma clase lo podrán llamar.
Si no usamos ni public ni private, lo podrá llamar
cualquier método que esté en el mismo paquete.
88
Ocultamiento de información Por ejemplo: class Ejemplo { public static void main(String[] args) { double a= Otra.porDos(7); } } class Otra { private static double porDos(double numero) { return numero*2; } } 89
Ocultamiento de información Al compilar este programa nos sale el
siguiente mensaje de error: The method factorial(int) from the type Otra is not visible Dado que ambos métodos están en diferentes clases,
no podemos llamar al método porDos desde el main, pues lo declaramos como private.
90
Ocultamiento de información Para llamarlo desde el main deberíamos incluir a ambos
métodos en la misma clase: class Ejemplo { public static void main(String[] args) { Ya no es double a= porDos(7); problema } que sea private private static double porDos(double numero) { return numero*2; } } 91
Ocultamiento de información Si declaramos una clase como public se
aplica lo mismo que dijimos para los métodos, es decir, se puede acceder a ella desde cualquier parte. Es decir, desde cualquier clase en cualquier paquete.
Si no usamos ni public ni private (como lo
hemos hecho hasta ahora) quiere decir que se puede acceder a ella dentro del mismo paquete donde se creó la clase.
Una clase no puede ser private. 92
Ocultamiento de información Lo anterior era necesario que lo supieran. Sin
embargo, para el tipo de programas que haremos en el curso no necesitan hacerse problema por declarar a clases y métodos como públicos o privados. Sigan haciendo los programas como los
hemos estado haciendo hasta ahora, es decir:
• No anteponemos ni public ni private en las clases • Todos los métodos los declaramos como public.
93
Ocultamiento de información Sin embargo, pondremos atención a lo que
significa declarar un atributo como private.
Podemos declarar los atributos como public
o private.
De esto depende desde donde podremos
verlos o cambiarlos.
Con ver o cambiar se entiende que se
pueden ver o cambiar los atributos de un objeto de esa clase. 94
Ocultamiento de información Si un atributo es declarado como public, se
puede ver y cambiar desde cualquier parte. Es decir, desde cualquier clase en cualquier paquete.
Si un atributo es declarado como private,
sólo puede ser visto o cambiado dentro de la clase.
Si no se incluye la palabra public o private
el atributo se puede ver o cambiar desde cualquier clase que esté en el mismo paquete. 95
Ocultamiento de información Habíamos hecho la siguiente clase Cuadrado: class Cuadrado { double lado; public Cuadrado(double ld) { lado = ld; } public double area() { return lado*lado; } } 96
Ocultamiento de información Podemos tener también:
Opción 1 class Cuadrado { public double lado;
}
Opción 2 class Cuadrado { private double lado;
public Cuadrado(double ld) {...}
public Cuadrado(double ld) {...}
public double area() {...}
public double area() {...} }
97
Ocultamiento de información: Opción 1 Como ejemplo de la Opción 1, supongamos
que tenemos el siguiente programa: class Ejemplo { public static void main(String[] args) {
Cuadrado c1= new Cuadrado(3); ... double l= c1.lado; ... c1.lado= 8; } } class Cuadrado
{ public double lado; ... } 98
Ocultamiento de información: Opción 1 En la Opción 1 declaramos a lado como
public. Esto quiere decir que si creamos un objeto de la clase Cuadrado su atributo lado se podrá ver y cambiar desde cualquier parte. Es decir, desde cualquier clase en cualquier paquete.
En el ejemplo anterior el main está en una
clase separada de la clase Cuadrado.
Veamos ahora paso a paso lo que pasa en el
ejemplo anterior. 99
Ocultamiento de información: Opción 1 Cuadrado c1= new Cuadrado(3);
Aquí estamos creando un objeto de la clase Cuadrado.
c1 lado= 3.0
Como al definir la clase Cuadrado especificamos que el atributo lado era public, cada vez que creamos un objeto de la clase Cuadrado podremos ver o cambiar sus atributos desde cualquier parte. 100
Ocultamiento de información: Opción 1 double l= c1.lado; Aquí estamos viendo el atributo lado de c1 desde el método main
El método main está en una clase separada de la clase Cuadrado, pero podemos ver el atributo lado de c1 pues al definir la clase Cuadrado este atributo fue declarado como public. 101
Ocultamiento de información: Opción 1 c1.lado = 8;
Aquí estamos cambiando el atributo lado de c1 desde el método main
El método main está en una clase separada de la clase Cuadrado, pero podemos cambiar el atributo lado de c1 pues al definir la clase Cuadrado este atributo fue declarado como public.
102
Ocultamiento de información: Opción 2 Como ejemplo de la Opción 2, supongamos que
tenemos el siguiente programa:
class Ejemplo { public static void main(String[] args) {
Cuadrado c1= new Cuadrado(3); ... double l= c1.lado; ... c1.lado= 8; } } class Cuadrado
{ private double lado; ... }
103
Ocultamiento de información: Opción 2 Si queremos compilar el programa anterior
nos saldrá el siguiente mensaje: The field Cuadrado.lado is not visible
Como el atributo lado fue declarado como
private en la defición de la clase Cuadrado, cuando creamos un objeto de esta clase su atributo lado no es visible fuera de esta clase.
104
Ocultamiento de información Como vimos en el programa de la Opción 2,
en el main no podemos simplemente escribir c1.lado pues:
• lado fue declarado como private, • y el main no está en la clase Cuadrado.
Sólo los métodos que están dentro de la clase
Cuadrado podrán acceder directamente a los atributos de los objetos.
La clase Cuadrado que mostramos antes tenía
dos métodos, el constructor y area. En ambos, decíamos simplemente lado para acceder al atributo lado del objeto implícito. 105
Ocultamiento de información Supongamos que agregamos a la clase Cuadrado de
la Opción 2 el método equals. Este método recibe como argumento un objeto de la clase Cuadrado y retorna true si el lado del objeto implícito es igual al lado del objeto que recibe como argumento. En caso contrario retorna false. class Cuadrado { private double lado; public Cuadrado(double ld) {...} public double area() {...} public boolean equals (Cuadrado c) {...}
}
106
Ocultamiento de información 1. Pregunta:
¿Podemos dentro del método equals escribir simplemente c.lado si lado fue declarado como private en la definición de la clase Cuadrado? Implemente el método equals
107
Ocultamiento de información
En el método equals podemos decir simplemente c.lado pues este método está dentro de la clase Cuadrado, por lo tanto dentro del método tenemos acceso directo a los atributos tanto del objeto implícito como de los objetos (de la clase Cuadrado) que recibimos como argumento.
3. public boolean equals (Cuadrado c)
{ if (lado == c.lado) return true; else return false; } 108
Ocultamiento de información ¿Pero por qué declaramos un atributo como
private?
1. Porque queremos mantener la integridad de los objetos que creamos.
3. Porque pueden haber atributos al que sólo algunas personas deberían tener acceso.
109
Ocultamiento de información 1. Porque queremos mantener la integridad de
los objetos que creamos.
Por ejemplo, si tenemos la siguiente clase cuadrado: class Cuadrado { public double lado; public Cuadrado(double ld) {...} public double area() {...} } Podríamos tener lo siguiente desde una clase externa: Cuadrado c1= new Cuadrado (4); c1.lado= -3;
110
Ocultamiento de información En este caso estamos creando un cuadrado
con un lado negativo. El lado de un cuadrado no puede ser negativo,
por lo tanto al declarar al atributo lado como public nos arriesgamos a no mantener la integridad de los objetos de la clase Cuadrado.
111
Ocultamiento de información 1. Porque pueden haber atributos al que sólo
algunas personas deberían tener acceso. class Cuenta { String rut; int saldo; String password;
Por ejemplo saldo
.... }
112
Ocultamiento de información Por estas razones, cuando creamos una Clase,
debemos preocuparnos de que los métodos de esa Clase se preocupen de mantener la integridad tanto de los objetos que reciben como argumento, como de los objetos que se crean dentro de los métodos. Ahora que declaramos los atributos como
private, debemos crear métodos que nos permitan ver y cambiar los atributos de los objetos desde clases externas.
113
Ocultamiento de información A los métodos que nos permiten cambiar un atributo
los llamaremos métodos setters.
Se acostumbra llamar al método:
<set><nombre del atributo> Por ejemplo: setLado En el ejemplo anterior, ahora que el atributo lado es
private, para cambiarlo desde fuera de la clase Cuadrado ya no podemos decir por ejemplo: c.lado= 3;
sino que diremos
c.setLado(3); 114
Ocultamiento de información A los métodos que nos permiten ver un atributo los
llamaremos métodos getters.
Se acostumbra llamar al método:
<nombre del atributo> Por ejemplo: getLado En el ejemplo anterior, ahora que el atributo lado es
private, para verlo desde fuera de la clase Cuadrado ya no podemos decir por ejemplo: double l= c.lado;
sino que diremos
double l= c.getLado(); 115
Ocultamiento de información: Setters Por ejemplo, para la clase Cuadrado podemos crear el
siguiente método setLado. public void setLado(double ld) { if (ld < 0) throw new RuntimeException ("Intento de darle valor negativo al lado de un Cuadrado");
else lado= ld; }
116
Ocultamiento de información: Setters Luego si tratamos de correr el siguiente programa: class Ejemplo { public static void main(String[] args) { Cuadrado c1= new Cuadrado(); c1.setLado(-3); } } class Cuadrado { private double lado; public void setLado(double ld) { if (ld < 0) throw new RuntimeException ("Intento de darle valor negativo al lado de un Cuadrado"); else lado= ld; } } 117
Ocultamiento de información: Setters Saldrá el siguiente mensaje de error: Exception in thread "main" java.lang.RuntimeException: Intento de darle valor negativo al lado de un Cuadrado at Cuadrado.setLado(Ejemplo.java:16) at Ejemplo.main(Ejemplo.java:6)
118
Ocultamiento de información: Setters El resultado de usar esta excepción es que se
detiene la ejecución del programa cuando tratamos de asignarle un valor negativo a lado. En este ejemplo usamos excepciones, sin
embargo en el curso no veremos el manejo de excepciones. Este era sólo un ejemplo para que tuvieran
cierta noción del uso excepciones. 119
Ocultamiento de información: Setters El método anterior lo podríamos cambiar por: public void setLado(double ld) { if (ld < 0) { System.out.println("No le puede asignar "+ "a lado un valor negativo\n"+ "El valor del atributo lado" + " no fue cambiado"); } else lado= ld; }
120
Ocultamiento de información: Setters En este caso, cuando le tratamos de asignar al
lado del objeto implícito un valor negativo, no terminamos con la ejecución del programa pero sí imprimos un mensaje. Además, para mantener la integridad de los
objetos de la clase Cuadrado, si ld es negativo, no cambiamos el valor del atributo lado (del objeto implícito).
121
Ocultamiento de información: Getters Dado que en la clase Cuadrado declaramos al
atributo lado como private, no sólo necesitamos un método setter para cambiar el valor del atributo sino que también necesitamos un método getter para ver el valor de este.
Para la clase Cuadrado podemos crear el
siguiente método getter.
public double getLado() { return lado; } 122
Ocultamiento de información: Getters public void setLado(double ld) { Fíjense que en general (no siempre) if (ld < 0) en los métodos setters {... } se recibe algo pero no retorna else nada y en cambio en los getters lado= ld; siempre se retorna algo pero no recibe nada. } public double getLado() { return lado; } 123
Ocultamiento de información: Getters Veamos ahora un ejemplo de un método
getter que no retorna el valor de un atributo a menos que se cumplan ciertas condiciones. Dada la clase Cuenta:
124
Ocultamiento de información: Getters Escriba un método getter que reciba como argumento
un String (en este caso el getter sí recibe un argumento). Este método retorna el saldo sólo si el String que recibe es igual al password del objeto con el cual se está llamando al método. En caso contrario imprime “El password es incorrecto” y retorna -1. class Cuenta { private String rut; private int saldo; private String password; .... }
125
Ocultamiento de información public int getSaldo(String pass) { if(pass.equals(password)== false) { System.out.println("El password es incorrecto"); return -1; } else return saldo; }
126
Ocultamiento de información class Cuenta { private String rut; private int saldo; private String password; public Cuenta(String r, int s, String p) { rut= r; if(s >= 0) saldo= s; else saldo= 0; password= p; } public int getSaldo(String pass) {... } }
127
Ocultamiento de información Supongamos que también tenemos la clase
Ejemplo que contiene el main: class Ejemplo { public static void main(String[] args) { Cuenta c1= new Cuenta("99999-1",30000, "123"); System.out.println(c1.getSaldo("111")); } }
¿Qué sucederá al correr este programa?
128
Ocultamiento de información Se imprimirá en pantalla: El password es incorrecto -1
Volviendo un poco atrás en la materia: ¿Por qué igual hacemos que el método retorne -1? Porque si el encabezado del método dice que debe retornar algo entonces debemos retornar sí o sí un valor. Por otro lado si el método es void no debe retornar nada (puede tener un return vacío: return; )
129
Atributos estáticos Así como tenemos métodos estáticos y de
instancia también podemos tener atributos estáticos y de instancia. ¿Como distinguíamos entre un método estático y de instancia?
• Si es estático el encabezado tiene la palabra
static. • Si no tiene la palabra static entonces es de instancia.
Lo mismo se aplica a los atributos. Si no
tienen la palabra static entonces es un atributo de instancia, lo cual quiere decir que cada objeto de la clase va a guardar el valor del atributo y este valor puede variar entre un
130
Atributos estáticos Por lo tanto hasta ahora, todos los atributos
que hemos usado han sido de instancia. Si cuando declaramos un atributo anteponemos la palabra static entonces este atributo será un atributo estático. Si un atributo es estático entonces habrá sólo una copia del valor de este atributo para toda la clase (no por cada objeto). Este no es un atributo de los objetos de la clase. Es un atributo de la clase.
131
Atributos estáticos Por ejemplo, podemos tener la siguiente clase
(ejemplo del libro):
class Auto { private double consumo; private double kilometros; public static double precioBencina= 600; ..... }
Como es público, para referirnos al valor de
este atributo escribiremos (si estamos en otra clase): Auto.precioBencina 132
Atributos estáticos Si fuera privado tendríamos que crear métodos
para ver y cambiar este valor. Podemos además incluir la palabra final. class Auto { private double consumo; private double kilometros; public static final double precioBencina= 600; ..... }
133
Atributos estáticos Esto quiere decir que no se podrá cambiar el valor
inicial que le dimos al atributo (ni dentro ni fuera de la clase).
Es decir, no podremos escribir:
Auto.precioBencina= 650; Las variables también se pueden declarar como final.
Por ejemplo, podríamos escribir: final int a=300; Esto quiere decir que en ningún momento podremos cambiar el valor de a. Es decir no podremos escribir: a=400; 134
Método toString para Clases Cuando teníamos la clase Complejo: class Complejo { double real; double imaginaria; public Complejo(double r, double imag) { real= r; imaginaria= imag; } } 135
Método toString para Clases No podíamos llegar y escribir:
System.out.println(c1); Donde c1 es un objeto de la clase Complejo
En este caso se imprime:
Complejo@18a992f Java imprime un String que contiene la clase y el espacio de memoria donde se guarda el objeto que estamos tratando de imprimir.
136
Método toString para Clases Por esta razón debíamos imprimir sus atributos
uno por uno:
System.out.println(c1.real+ " + "c1.imaginaria+"i");
Sin embargo, Java nos permite crear el método
toString para imprimir los objetos de una clase de la forma que nos parezca adecuada.
Este método se puede incluir en cualquier clase
que nosotros creemos, y el encabezado se ve así: public String toString(){...}
137
Método toString para Clases Como ven este método retorna un String. Este String que retorna, será lo que se
imprima cuando llamemos a los métodos print y println.
Por ejemplo, podemos crear el siguiente
método toString para la clase Complejo: public String toString() { String s= real+ " + "+imaginaria+"i"; return s; } 138
Método toString para Clases class Complejo { double real; double imaginaria; public Complejo(double r, double imag) { Este método se real= r; debe incluir dentro imaginaria= imag; de la clase Complejo } public String toString() { String s= real+ " + "+imaginaria+"i"; return s; } } 139
Método toString para Clases Ahora que ya tenemos el método toString
para la clase Complejo, podemos tener el siguiente programa: class Ejemplo2 { public static void main(String[] args) { Complejo c1= new Complejo(2,3.5); System.out.println(c1); } Imprime: }
2.0 + 3.5i 140
Método toString para Clases Recuerden que podemos crear el método
toString para cualquier clase. Una vez que creemos este método, Java sabrá exactamente que hacer cuando le pidamos que imprima un objeto a través de los métodos print y println. Además, como se explicó la clase pasada, cuando escribimos: algo + un String Toda la expresión se vuelve un String.
141
Método toString para Clases Por esta razón podíamos escribir: String s= real + " + “ +imaginaria+ "i";
Por ejemplo, si escribimos: int a= 14; String s1= a + ""; String s2= "Yo corrí "+ 15.5 +" kilómetros";
En s1 se guarda el String “14”. En s2 se guarda el String “Yo corrí 15.5 kilómetros” 142
Arreglo de Objetos Como dijimos anteriormente, cuando se crea
un arreglo de largo n, es como si creáramos n variables del tipo que definimos al crear el arreglo. Por ejemplo, si escribimos:
int[] a= new int[10]; Es como si creáramos 10 variables de tipo int donde la primera se llama a[0], la segunda se llama a[1] etc. a[0] a[1] a[9] ........................
143
Arreglo de Objetos Además dijimos que Java inicializa
automáticamente los elementos de un arreglo cuando creamos el arreglo: int[] a= new int[10]; Aquí lo estamos creando
En este caso como es un arreglo de enteros, a
cada elemento le asigna el valor 0: a[0]
a[1]
0
0
a[9] ........................
0
144
Arreglo de Objetos En el caso de los objetos se aplican las mismas reglas.
Cuando crean un arreglo de objetos es como si crearan varias referencias al mismo tiempo. Cuadrado[] c= new Cuadrado[10];
Aquí lo estamos creando el arreglo de referencias. NO LOS OBJETOS
En este caso es como si creáramos 10 variables que
hacen referencia a objetos de la clase Cuadrado.
145
Arreglo de Objetos Sin embargo, aun no le hemos asignado un
objeto a esas variables. c[0]
c[1]
c[9] ........................
Así como Java inicializa los elementos de un
arreglo en 0 cuando estos eran numéricos, Java también inicializa los elementos de un arreglo cuando estos son referencias.
146
Arreglo de Objetos Cuando los elementos de un arreglo son
referencias (arreglo de objetos), Java automáticamente le asignará null a cada elemento (referencia) del arreglo. c[0]
c[1]
c[9] ........................
Así se representa null 147
Arreglo de Objetos Si queremos asignarle un objeto al elemento
c[0], debemos escribir: c[0]= new Cuadrado(3); c[0]
c[1]
c[9] ........................
lado= 3 Ahora c[0] hace referencia a un objeto de la clase Cuadrado 148
Arreglo de Objetos Cuando teníamos:
Cuadrado c= new
Cuadrado(3); Decíamos:
c.setLado(5.6); double l= c.getLado();
Ahora tenemos:
Cuadrado[] c= new Cuadrado[10]; c[0]= new Cuadrado(3);
Ahora decimos:
c[0].setLado(5.6); double l= c[0].getLado();
149
Arreglo de Objetos Los arreglos de objetos son muy útiles pues en
vez de guardar un sólo dato en cada elemento del arreglo guardamos muchos datos que están relacionados entre sí. a[0]
a[1]
1.5
4.5
a[9]
....
a[0]
a[1]
6.0
a[9]
.... ... ... ...
... ... ...
... ... ...
Estos muchos datos relacionados entre sí se
guardan en un objeto.
150
Arreglo de Objetos Por ejemplo, supongamos que tenemos la
siguiente clase Alumno: class Alumno { private String nombre; private String dir; private double prom; private double[] notas; ... ... }
151
Arreglo de Objetos Si tenemos un Alumno, tiene sentido que
guardemos sus notas en un arreglo. notas[0] 5.5
notas[1] 4.5
....
notas[n-1] 6.0
Pero:
• ¿De qué curso es cada nota? • ¿Cuándo tomó cada curso? • ¿Cuántos créditos tiene cada curso?
152
Arreglo de Objetos Dado que necesitamos más que sólo la nota del curso,
podemos crear la clase Nota y en cada elemento del arreglo guardaremos en vez de un double una Nota (en realidad una referencia a un objeto de la clase Nota). class Alumno { private String private String private double private Nota[] ... ... }
nombre; dir; prom; notas;
153
Arreglo de Objetos Por lo tanto ahora podremos tener un arreglo
de referencias a objetos, donde cada objeto es una instancia de la clase Nota: notas[0]
notas[1]
notas[n-1]
....
nota: 5.5 año: 2006 semestre:1 créditos: 10 curso:ING1112
nota: 4.5 año: 2006 semestre:1 créditos: 5 curso:ING1320
nota: 6.0 año: 2006 semestre:1 créditos: 15 curso:ING2020
154
Almacenamiento secundario Los computadores manipulan datos
almacenados en su memoria principal (almacenamiento primario). Sin embargo, esta memoria es limitada y
volátil, por lo que se hace necesario emplear otro tipo de almacenamiento que sea perdurable y cuya disponibilidad (en cuanto a espacio y costo) sea más conveniente.
155
Almacenamiento secundario: Dispositivos Discos magnéticos (discos duros) Diskettes (discos flexibles) Discos ópticos (CD-ROMs) Cintas magnéticas (usadas para respaldos) Pen drive
156
Sistema de archivos Permite operar con
distintos dispositivos de almacenamiento secundario de una forma estándar.
Organización jerárquica. Operaciones típicas: • Leer • Escribir • Cambiar el nombre • Crear una carpeta • Borrar un archivo o una carpeta 157
Tipos de archivos Los archivos pueden ser de distintos tipos,
dependiendo del tipo de datos que almacenen. Ejemplos:
• Archivos de texto, cuyos datos están en formato ASCII • Programas ejecutables en formato binario • Imágenes (bitmaps, jpeg, gif) • Sonido (wav) • Video (avi)
En este curso nos limitaremos a trabajar con
archivos que guardan datos en formato de texto (ASCII). 158
Clases para manipular archivos Manipulación de archivos
• class
File
Para leer archivos
• class • class
FileReader BufferedReader
Para leer archivos
Para escribir en archivos
• class • class
FileWriter BufferedWriter
Para escribir en archivos
159
Clase File Clase de objetos que permite manejar
archivos: Class File Constructor de la clase File: File archivo = new File("datos_entrada.txt"); Aquí estamos creando un objeto de la clase File.
Este archivo puede o no existir. Pero si queremos leer su contenido, debería existir y encontrarse en la misma carpeta que el proyecto de Java donde está este código.
160
Métodos útiles Cuando se ha establecido una asociación
válida, decimos que el archivo está abierto. Nota: para utilizar archivos hay que importar
el paquete java.io.*; Para importar lo único que necesitamos es
escribir al principio del programa: import java.io.*;
161
Métodos útiles Una vez creado un objeto File, se puede utilizar uno
de los siguientes métodos para obtener información sobre el archivo:
Nombres de archivo • public String getName() • public String getAbsolutePath() • public boolean renameTo(File nuevoNombre) Comprobaciones • public boolean exists() • boolean canWrite() • public boolean canRead() Información general del archivo • public long length()
Como ven todos son métodos de instancia y por lo tanto se llaman con un objeto de la clase File
162
Un ejemplo simple Supongamos que el archivo ejemplo.txt ya
ha sido creado y contiene lo siguiente:
Este es un archivo de prueba. Va a ser utilizado en el curso ING1310. ¿Qué imprime el siguiente programa?
163
Un ejemplo simple import java.io.*; class Ejemplo { public static void main(String[] args) { File archivo = new File("ejemplo.txt"); if (archivo.exists()) System.out.println("El archivo existe"); else System.out.println("El archivo no existe"); System.out.println(archivo.getName()); System.out.println(archivo.getAbsolutePath()); System.out.println(archivo.length()); } }
164
Un ejemplo simple El programa anterior imprime: El archivo existe ejemplo.txt C:\Documents and Settings\Vanny\My Documents\Trabajo\Ejemplo2\ejemplo.txt 70
El archivo ejemplo.txt debe estar en la misma
carpeta donde está el proyecto.
165
Streams Una vez que un archivo está abierto, podemos
tener acceso a él a través de un objeto de tipo stream – una secuencia de datos:
• Un stream de input tiene una fuente desde donde
vienen los datos • Un stream de output tiene un destino a donde van los datos
166
Leer y Escribir Leer … Abrir archivo while (hay datos) { Leer información } Cerrar archivo
Escribir … Abrir archivo while (hay datos) { Escribir información } Cerrar archivo
167
Lectura: Clase FileReader Clase de objetos que permite leer archivos:
Class FileReader Este es el que usaremos
Constructores de la clase FileReader:
public FileReader(File file) Crea un nuevo objeto de la clase FileReader y recibe como argumento un objeto de la clase File.
public FileReader(String fileName) Crea un nuevo objeto de la clase FileReader y recibe como argumento el nombre de un archivo.
168
Lectura: Clase FileReader Ejemplo de cómo crear un objeto de la Clase
FileReader dado un objeto de la clase File FileReader leer = new FileReader(archivo);
Aquí estamos creando un objeto de la clase FileReader.
Aquí le entregamos al constructor un objeto de la clase File. En este caso archivo es el nombre de un objeto de la clase File
169
Lectura: Clase FileReader Para leer datos desde un archivo, vinculamos
un objeto stream* de input al archivo: File archivo = new File(“ejemplo.txt");
FileReader leer = new FileReader(archivo);
*
Un objeto de la clase FileReader es un objeto stream
170
Lectura: Clase FileReader Para leer carácter a carácter se usa el método:
public int read() Lee un caracter y su valor de retorno es int. Si no hay nada más que leer (final del archivo) retorna -1. Para cerrar el Stream se usa el método:
public void close() Fíjense en que ambos métodos son de instancia. Es
decir, para llamarlos escribiremos: leer.read() y leer.close()
Donde leer es un objeto de la clase FileReader
171
Lectura: Clase FileReader Cuando empezamos a leer un archivo el
cursor se ubica al principio de la primera línea. Este es un archivo de prueba. Va a ser utilizado en el curso ING1310.
Luego, cada vez que llamamos al método
read se lee un carácter y el cursor se posiciona en el siguiente carácter. Este es un archivo de prueba. Va a ser utilizado en el curso ING1310.
172
FileReader: Ejemplo import java.io.*; class Ejemplo2 { public static void main(String[] args) throws IOException { File archivo = new File("ejemplo.txt"); FileReader leer = new FileReader(archivo); int i, valor; char c; for(i= 1; i <= archivo.length(); i++) { valor = leer.read(); c = (char) valor; System.out.println(i + " : " + c + " [" + valor + "]"); } leer.close(); } } 173
FileReader: Ejemplo El programa anterior imprime: 1 : E [69] 2 : s [115] 3 : t [116] ... 29 : . [46] 30 : [13] 31 : [10] 32 : V [86] ... 69 : 0 [48] 70 : . [46]
Aquí nos saltamos pues queda muy largo
174
Lectura: Clase BufferedReader Clase de objetos que permite leer archivos
(más eficiente que FileReader): Class BufferedReader El constructor de la clase BufferedReader
recibe como argumento un objeto de la clase FileReader.
BufferedReader buffer = new BufferedReader(leer);
Objeto de la clase FileReader 175
Lectura: Clase BufferedReader File archivo = new File(“ejemplo.txt");
FileReader leer = new FileReader(archivo);
BufferedReader buffer = new BufferedReader(leer);
176
Lectura: Clase BufferedReader Por medio de la clase BufferedReader
podemos leer por líneas (más eficiente) o caracter a carácter.
Para leer línea por línea usamos el
método: public String readLine()
• Lee una línea, sin considerar el caracter de salto de
línea ('\r' y '\n') • Retorna el contenido de la línea (sin incluir '\r' ni '\n‘). • Si se termina el archivo retorna null
177
Lectura: Clase BufferedReader Para leer caracter a caracter se usa el
método: public int read() Lee un caracter y su valor de retorno es int. Si no hay nada más que leer (final del archivo) retorna -1. Finalmente, para cerrar el Stream usamos el
método: public void close() Fíjense que estos tres métodos son de
178
Lectura: Clase BufferedReader Cuando empezamos a leer un archivo el
cursor se posiciona al principio de la primera línea, y cada vez que llamemos al método read o al método readLine este cursor se moverá. Si llamamos al método read, una vez leído el
carácter el cursor se moverá al siguiente carácter.
Si llamamos al método readline, una vez
leída la línea el cursor se moverá a la siguiente línea.
179
Lectura: Clase BufferedReader Todo método (no sólo el main) para manejar
archivos y streams debe estar preparado para recibir excepciones: public static void main(String[] args) throws IOException
{ ... }
Cuando tenemos Streams (FileReader o BufferedReader) debemos incluir esto en el encabezado del método
180
BufferedReader: Primer ejemplo import java.io.*; class Ejemplo2 { public static void main(String[] args) throws IOException { File archivo = new File("ejemplo.txt"); FileReader leer = new FileReader(archivo); BufferedReader buffer = new BufferedReader(leer);
181
BufferedReader: Primer ejemplo int i, valor; char c; for(i = 1; i <= 10; i++) { valor = buffer.read(); c = (char) valor; System.out.println(i + " : " + c + " [" + valor + "]"); } System.out.println(buffer.readLine()); leer.close(); buffer.close(); } }
182
BufferedReader: Primer ejemplo El programa anterior imprime: 1 : E [69] 2 : s [115] 3 : t [116] 4 : e [101] 5 : [32] 6 : e [101] 7 : s [115] 8 : [32] 9 : u [117] 10 : n [110] archivo de prueba.
183
BufferedReader: Segundo ejemplo import java.io.*; class Ejemplo2 { public static void main(String[] args) throws IOException { File archivo = new File("ejemplo.txt"); FileReader leer = new FileReader(archivo); BufferedReader buffer = new BufferedReader(leer); String linea; linea = buffer.readLine(); while (linea != null) { System.out.println(linea); linea = buffer.readLine(); } } } 184
BufferedReader: Segundo ejemplo El programa anterior imprime: Este es un archivo de prueba. Va a ser utilizado en el curso ING1310.
185
Conversión de tipos Para mayor claridad, los 5 métodos que
veremos a continuación son estáticos y la forma en que se presentan no se refiere a su encabezado, sino que: Retorna Se invoca Recibe
String
String.valueOf
(int);
Convertir de número int a String.
String String.valueOf(double); Convertir de número double a String. 186
Conversión de tipos int Integer.parseInt(String); Convertir un String a int (el String no debe tener letras o caracteres no numéricos).
double Double.parseDouble(String); Convertir un String a double (ídem a parseInt).
boolean Character.isDigit(char); Devuelve true si el char es un dígito de 0 a 9.
(char) Convertir a caracter (cast)
187
Conversión de tipos class Ejemplo { public static void main(String[] args) { String s= "345"; int a= Integer.parseInt(s); System.out.println(a); char c= '6'; System.out.println(Character.isDigit(c)); } }
Imprime:
345 true 188
Ejemplo: Cálculo de promedio Queremos calcular el promedio de notas del archivo
notas.txt: CANEPA 5.3 GAULE 4.8 GOTTLIEB 6.0 MONTABONE 4.6 MORALES 5.8 NEIRA 6.0 PEREZ 4.8 REUTTER 6.0 RIVEROS 6.6 SANDERS 5.5 VALDIVIA 6.0 VILA-ECHAGUE 5.5
189
Ejemplo: Cálculo de promedio Antes de ver la solución debemos conocer el método
substring (método de instancia): public String substring (int beginindex) s.substring(n): Devuelve el substring de s ubicado entre las posiciones n y(s.length()-1). public String substring (int beginindex,int endindex)
s.substring(n,m): Devuelve el substring de s ubicado entre las posiciones n y m-1.
190
Ejemplo: Cálculo de promedio import java.io.*; class Ejemplo2 { public static void main(String[] args) throws IOException { File archivo = new File("notas.txt"); FileReader leer = new FileReader(archivo); BufferedReader buffer = new BufferedReader(leer); double suma_notas = 0.0; int numero_alumnos = 0; String nota, linea;
191
Ejemplo: Cálculo de promedio linea = buffer.readLine(); while (linea != null) { nota = linea.substring(linea.indexOf(' ')+1); suma_notas = suma_notas + Double.parseDouble(nota); numero_alumnos++; linea = buffer.readLine(); } System.out.println("Promedio del curso : +suma_notas/numero_alumnos); leer.close(); buffer.close(); } }
192
Clases para manipular archivos Manipulación de archivos
• class
File Ya vimos esto
Para leer archivos
• class • class
FileReader BufferedReader
Para escribir en archivos
• class • class
Ahora veremos como escribir en archivos
FileWriter BufferedWriter
193
Escritura: Clase FileWriter Clase de objetos que permite escribir en
archivos: Class FileWriter Constructor de la clase FileWriter:
public FileWriter(File file)
• Crea un nuevo objeto de la clase FileWriter y recibe como argumento un objeto de la clase File.
• En el caso que no exista se crea. • Si el archivo existe se borra todo su contenido.
194
Escritura: Clase FileWriter Para escribir datos a un archivo, vinculamos un
objeto stream de output* al archivo: File archivo = new File(“ejemplo.txt");
FileWriter escribir = new FileWriter(archivo);
Para cerrar el Stream:
public void close() *Un objeto de la clase FileWriter es un objeto Stream de output 195
Escritura: Clase FileWriter Otro constructor de la clase FileReader:
public FileWriter(File file, boolean append)
• Crea un nuevo objeto de la clase FileWriter y recibe como argumento un objeto de la clase File.
• Si el segundo argumento es true, entonces se empieza a escribir al final del archivo
• Si el segundo argumento es false, en el caso del que el
archivo que no exista se crea y si existe se borra todo su contenido 196
Escritura: Clase FileWriter Con objetos de esta clase podemos escribir tanto
caracteres como Strings en un archivo. Sin embargo este proceso puede ser muy ineficiente.
Por esta razón, en vez de usar objetos de esta clase
para escribir, usaremos objetos de la clase BufferedWriter (más eficientes).
Igual necesitaremos crear objetos de la clase
FileWriter pues el constructor de la clase BufferedWriter recibe como argumento un objeto de esta clase.
Además, dependiendo del objeto FileWriter es que se
comenzará a escribir al principio o al final del archivo (append). 197
Escritura: Clase BufferedWriter Clase de objetos que permite escribir en
archivos (más eficiente que FileWriter): Class BufferedWriter El constructor de la clase BufferedWriter
recibe como argumento un objeto de la clase FileWriter.
BufferedWriter buffer = new BufferedWriter(escribir);
Objeto de la clase FileWriter 198
Escritura: Clase BufferedWriter File archivo = new File(“ejemplo.txt");
FileWriter escribir = new FileWriter(archivo);
BufferedWriter buffer = new BufferedWriter(escribir);
199
Escritura: Clase BufferedWriter Para escribir se puede usar el método:
public void write(…)
• Escribe un caracter o String. • Cuando empezamos a escribir en un archivo el
cursor se posiciona al principio de la primera línea (o al final si usamos append). • Cada vez que llamemos al método, primero se escribirá y luego el cursor quedará posicionado al final de lo que se escribió (no se salta una línea).
200
Escritura: Clase BufferedWriter Si queremos saltarnos a la siguiente línea
debemos usar el método: public void newLine() Esto, dado que no en todos los sistemas “\n”significa nueva línea Para cerrar el Stream:
public void close()
201
BufferedWriter: Ejemplos Ejemplo 1:
Supongamos que tenemos el un archivo llamado notas.txt. Haga un programa que copie el contenido de este archivo en otro archivo llamado copia_notas.txt. Ejemplo 2 (profesor Ricardo Zilleruelo):
Programa que escriba en un archivo (nombre dado por el usuario) lo que el usuario escribe desde la entrada estandar. Haga que lo guarde primero como .txt y luego como .doc (en general no se recomienda pero es para ver como funciona) 202
Solución Ejemplo 1 import java.io.*; class Ejemplo2 { public static void main(String[] args) throws IOException { File archivo = new File("notas.txt"); FileReader leer = new FileReader(archivo); BufferedReader b_read = new BufferedReader(leer); File salida = new File("copia_notas.txt"); FileWriter imprimir = new FileWriter(salida); BufferedWriter b_write= new BufferedWriter(imprimir);
203
Solución Ejemplo 1 String linea; linea = b_read.readLine(); while (linea != null) { b_write.write(linea); b_write.newLine(); linea = b_read.readLine(); } leer.close(); b_read.close(); b_write.close(); imprimir.close(); } }
204
Solución Ejemplo 2 (como .doc) import java.io.*; class Ejemplo2 { static public void main(String args[])throws IOException { System.out.print("nombre archivo?"); String nombre = In.readLine(); nombre= nombre+".doc"; BufferedWriter out = new BufferedWriter(new FileWriter(nombre)); String line; while(true){ line = In.readLine(); if(line.equals("terminar")) break; out.write(line); out.newLine(); } out.close(); } } 205
Resumen de archivos En resumen, de todas las clases que vimos
deben poner más atención a los métodos de las clases BufferedReader y BufferWriter (más eficientes) pues son los que usaremos para leer y escribir en archivos respectivamente. File FileReader BufferedReader read(), readLine() FileWriter BufferedWriter write(), newLine()
Las otras clases las necesitamos para crear
objetos de estas clases (BufferedReader y BufferWriter ).
206
Resumen de archivos Recuerden cerrar los Streams. Recuerden importar el paquete java.io Recuerden incluir throws IOException en el
encabezado de los métodos (no sólo el main).
Recuerden los métodos que permiten
convertir un String a un tipo primitivo y viceversa.
Recuerden el método substring. 207