TEMAS ESPECIALES DE COMPUTACIÓN LABORATORIO NÚMERO 4
Una interfaz en Java es una variante de la idea de Clase Abstracta. En una clase abstracta
es posible tener métodos con implementación pero, por lo menos, uno de los
métodos debe ser abstracto; es decir, sólo se declara la firma del método y no
debe estar implementado. En una interfaz, todos
los métodos deben ser abstractos.
Las interfaces son una forma de declarar un tipo que
se compone sólo de métodos abstractos y constantes, posibilitando que se
escriba cualquier implementación para esos métodos pero de eso se encargará(n)
la(s) clase(s) que implementará(n) la interfaz.
Una interfaz es una expresión de diseño puro, mientras que una clase es una mezcla de diseño e implementación.
1.
Cree la siguiente interfaz en
un archivo llamado Nomina.java.
Guarde el archivo y compílelo.
interface
Nomina
{
public static final String EMPRESA =
"Patito, S. A.";
public void detalleDeEmpleado(Nomina obj);
}
En las interfaces, los atributos deben declararse static final y
con un valor inicial. En java, los atributos “static final” no pueden modificar
su valor (son parecidos a constantes) y por eso se ha estandarizado su nombre
en mayúsculas. Después de la firma de los métodos de una interfaz, se debe
terminar con el punto y coma (;).
Una clase hereda a otra clase y puede implementar una
o más interfaces. La clase que implementa una interfaz tiene dos opciones:
1)
Implementar todos los métodos
de la interfaz.
2)
Implementar sólo algunos de
los métodos pero esa clase debe ser una clase abstracta (debe declararse con la
palabra abstract).
2.
Ahora vamos a implementar la
interfaz Nomina en la clase Empleado. Modifique la clase Empleado que se
encuentra en el archivo Empleado.java.
Guárdelo y compílelo.
1:public class Empleado implements Nomina
2:{
3:
String nombre = null;
4:
float salario = 0.0f;
5:
String titulo = "Empleado";
6:
7:
public Empleado(String nom, float sal)
8: {
9: nombre = nom;
10: salario = sal;
11: }
12:
13: public void
identificaEmpleado()
14: {
15: System.out.println("Iniciando el metodo identificaEmpleado
de Empleado");
16: System.out.println("Mi nombre es " + this.nombre +
", soy " + this.titulo + " de la empresa " + EMPRESA +
" y gano: $" + this.salario + "\n");
17: }
18:
19: public void
detalleDeEmpleado(Nomina emp)
20: {
21: if(emp instanceof Empleado)
22: ((Empleado)emp).identificaEmpleado();
23: }
24:}
OJO: A esta clase le quitamos el método main() y sólo se
va a poder compilar pero ya no se va a poder ejecutar como aplicación. Más
adelante vamos a crear una aplicación en la que se va a instanciar a la clase
Empleado.
3.
Vamos a crear una clase que
represente a los empleados eventuales de la empresa. Observando el siguiente
código, ¿Cómo se llama el archivo que contiene a la clase?
__________________________________. Sálvelo y compílelo.
public class EmpleadoEventual implements Nomina
{
String
nombre = null;
String
titulo = "Empleado Eventual";
public
EmpleadoEventual(String nom)
{
nombre = nom;
}
public void identificaEmpleado()
{
System.out.println("Iniciando el metodo
identificaEmpleado de EmpleadoEventual");
System.out.println("Mi nombre es "
+ this.nombre + ", soy " + this.titulo + " de la empresa "
+ EMPRESA + " y no tengo sueldo fijo\n");
}
public void detalleDeEmpleado(Nomina emp)
{
if(emp instanceof EmpleadoEventual)
((EmpleadoEventual)emp).identificaEmpleado();
}
}
4.
Tome la clase Gerente del
archivo Gerente.java y modifíquelo
al siguiente código. Sálvelo y compílelo.
public class Gerente extends Empleado
{
String
depto = null;
String
titulo = "Gerente";
public
Gerente(String nom, float sal, String dep)
{
super(nom, sal);
depto = dep;
}
public void identificaEmpleado()
{
System.out.println("Iniciando el metodo
identificaEmpleado de Gerente");
System.out.println("Mi nombre es "
+ this.nombre + ", soy " + this.titulo + " de la empresa "
+ EMPRESA + " y gano: $" + this.salario + "\n");
}
}
5.
Cree la siguiente clase en un
nuevo archivo. ¿Cómo se llamará ese archivo? ________________________________.
public class Directivo extends Empleado
{
String
titulo = "Directivo";
public
Directivo(String nom, float sal)
{
super(nom, sal);
}
public void identificaEmpleado()
{
System.out.println("Iniciando el metodo
identificaEmpleado de Directivo");
System.out.println("Mi nombre es "
+ this.nombre + ", soy " + this.titulo + " de la empresa "
+ EMPRESA + " y gano: $" + this.salario + "\n");
}
}
Sálvelo y compílelo.
6.
Ahora vamos a crear la
siguiente clase en su propio archivo. Sálvelo y compílelo. ¿Cómo se llamará ese
archivo? __________________________.
class ListaEmpleados
{
public
static void main(String arg[])
{
EmpleadoEventual emp01 = new
EmpleadoEventual("Juan Alvarez");
Empleado emp02 = new Empleado("Miguel
Lopez",9500.50f);
Gerente emp03 = new Gerente("Jose
Perez",15000,"Sistemas");
Directivo emp04 = new Directivo("Jorge
Valdez",18000);
emp01.detalleDeEmpleado(emp01);
emp02.detalleDeEmpleado(emp02);
emp03.detalleDeEmpleado(emp03);
emp04.detalleDeEmpleado(emp04);
}
}
El implementar una interfaz en una clase es como si
esa clase “heredara” a la interfaz. Por eso se dice que el uso de las
interfaces “simula” la herencia múltiple ya que una clase que implementa
interfaces también hereda a otra clase.
El diagrama de clases de todas las clases anteriores
quedaría de la siguiente manera.
Las clases Empleado y EmpleadoEventual, ¿A qué clase
heredan hacia arriba? (o sea, quien es su clase padre?)
__________________________________.
De la imagen anterior se concluye que:
La variable EMPRESA pertenece a la interfaz pero por
la implementación de la interfaz en las clases Empleado y EmpleadoEventual se
puede ocupar en ellas como si les perteneciera y como es una variable estática
no se requiere invocarla a través de una referencia a objeto (o sea, con el
operador punto). Empleado a su vez, la hereda a Gerente y Directivo.
El método detalleDeEmpleado se debe implementarse en
las dos clases que implementan la interfaz (Empleado y EmpleadoEventual). Si no
se hiciera así, las clases tendrían que ser abstractas. Empleado hereda el
método a Gerente y Directivo.
El método detalleDeEmpleado() recibe un objeto de la
interfaz Nomina como argumento. En la clase ListaEmpleados se observa que cada
invocación del método detalleDeEmpleado() envía como parámetro el mismo objeto
que invoca al método pero ¿Esos objetos son objetos tipo Nomina? (Si o No)
________________________________________________.
¿Por qué?
____________________________________________________________________________________.
Por ejemplo, en la sentencia emp01.detalleDeEmpleado(emp01); se afirma
que el argumento es un objeto de tipo EmpleadoEventual. Si nos dirigimos a la
clase EmpleadoEventual, se observa que en la implementación del método
detalleDeEmpleado() recibe el objeto de tipo Nomina (porque así está declarado
en la interfaz) por lo que hizo el cast implícito “hacia arriba” pero como
deseamos que en el método detalleDeEmpleado de esa clase en específico se
ejecute el método identificaEmpleado() de la clase EmpleadoEventual, entonces
se realiza el cast explícito “hacia abajo”. Para ello, se puede comprobar que
ese objeto (emp01) sí es un objeto o instancia de la clase EmpleadoEventual a
través del operador instanceof seguido del nombre de la clase y esto devuelve
un valor booleano true o false. Y para realizar el cast explícito se antepone
el tipo, al que se desea convertir, entre paréntesis, por lo que en la parte ((EmpleadoEventual)emp) el objeto
emp ya se convirtió a un objeto de tipo EmpleadoEventual y se invoca al método
identificaEmpleado de esa clase.
Escriba
aquí la salida de la ejecución de la clase ListaEmpleados:
________________________________________.