TEMAS ESPECIALES DE COMPUTACIÓN          LABORATORIO NÚMERO 4

 

INTEFACES

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: ________________________________________.