gravatar

06 Curso de Java OO. Clases abstractas e interfases

Resumen

Se estudiara el uso de clases abstractas, métodos abstractos, interfases, implementación de interfases

1. CLASES ABSTRACTAS
Clases abstractas
Sirven para modelar objetos de alto nivel, no contienen código, sino solo declaraciones. Todos sus métodos deben existir en sus clases hijas.
Una clase abstracta no puede ser instanciada (Crear un objeto a partir de ella).
Métodos abstractos
Estos métodos son parte de clases abstractas
Un método abstracto debe ser redefinido en las subclases.
Cada subclase puede definir el método de manera diferente.
Las clases abstractas pueden contener métodos que no son abstractos.
Laboratorio.
Que falta en el siguiente código?

Item.java

public abstract class Item {
    protected String titulo;
    protected float precio = 5.0f;
    public abstract boolean esAlquilable();
    public float getPrecio() {
        return precio;
    }
}
Pelicula.java
public class Pelicula extends Item {
    public boolean esAlquilable() {
        return true;
    }
}
Libro.java
public class Libro extends Item {
     public float getPrecio() {
        return 0.0f;
     }
}
TestAbstract.java
public class TestAbstract {
    public static void main (String[] args) {
        Pelicula pelicula = new Pelicula();
        Libro libro = new Libro();
        System.out.println(pelicula.esAlquilable());
        System.out.println(pelicula.getPrecio());
        System.out.println(libro.esAlquilable());
        System.out.println(libro.getPrecio());
    }
}

2. Interfases
Una interfase es totalmente abstracta; todos sus métodos son abstractos, sus atributos son públicos estáticos y final.
Una interfase define los métodos que otras clases pueden implementar pero no provee ninguna línea de código.
Una clase solo puede heredar de una superclase.
Una clase puede implementar muchas interfases; por lo que las interfases permiten herencia múltiple.
Ejemplos de interfases:


Las interfases describen la conducta que requiere muchas clases.
El nombre de una interfase por lo general es un adjetivo como Conducible, Ordenable, Ubicable.
Aquí se diferencia de una clase que usualmente es un sustantivo como Pelicula, Cliente, Alquiler
Las clases implementadas por una interfase pueden ser no tener ninguna relación unas con otras.
A diferencia de las clases heredadas de una superclase tiene similitudes.
Las clases que implementan una interface deben definir todos los métodos de la interface.

Conducible.java
public interface Conducible {
    public static final int MAXIMO_GIRO = 45;
    public abstract void girarIzquierda(int grados);
    public abstract void girarDerecha(int grados);
}

También se puede definir la interfase sin los calificadores public static final abstract, puesto que son implícitos.
Para declarar que una clase que implementa una interfase se usa implements
Laboratorio.

Que falta en el siguiente código?
Conducible.java
public interface Conducible {
    int MAXIMO_GIRO = 90;
    void girarIzquierda(int grados);
    void girarDerecha(int grados);
}
NaveArea.java
public class NaveAerea {
    protected char direccion;
    protected int altura;
    public void setDireccion(char direccion) {
        this.direccion= direccion;
    }
    public char getDireccion() {
        return this.direccion;
    }
}
Globo.java
public class Globo extends NaveAerea implements Conducible {
    private int volumenGas;
    public void setVolumenGas(int volumenGas) {
        this.volumenGas= volumenGas;
    }
    public int getVolumenGas() {
        return this.volumenGas;
    }
    public void girarDerecha(int grados) {
        if (getDireccion()=='N' && grados==90) setDireccion('E');
    }
}
Patin.java
public class Patin implements Conducible {
    public void girarDerecha(int grados) {
        System.out.println("Giro de "+grados+" grados a la derecha");
    }
    public void girarIzquierda(int grados) {
        System.out.println("Giro de "+grados+" grados a la izquierda");
    }
}
TestInterface.java
public class TestInterface {
    public static void main (String[] args) {
        Globo zepelin = new Globo();
        zepelin.setDireccion('N');
        zepelin.girarDerecha(90);
        System.out.println(zepelin.getDireccion());
        Patin patin = new Patin();
        patin.girarDerecha(90);
    }
}

EJERCICIO 1.
Crear la interfaz PuedeCantar (que es capaz de cantar), un interfaz muy simple que sólo posee un método cantar.

PuedeCantar.java

public interface PuedeCantar {
    public void cantar();
}
Crear la clase Persona que implemente el interfaz PuedeCantar y que cuando cante lo haga con las notas musicales.

Persona.java

public class Persona implements PuedeCantar {
    public void cantar() {
        System.out.println("do re mi fa sol la si");
    }
}

Crear la clase Canario y Gallo que implemente el interfaz PuedeCantar y que muestre como cantan
Canario.java
    ... System.out.println("pio pio pio") ...
Gallo.java
    ... System.out.println("ki ki ri ki") ...

Realice el programa que haga cantar a un canario y un tenor.

ProgramaInterfaz.java

public class ProgramaInterfaz {
     public static void main(String arg[]) {
        Persona pavaroti = new Persona();
        hacerCantar(pavaroti);
        Canario piolin = new Canario();
        hacerCantar(piolin);
        Gallo claudio = new Gallo();
        hacerCantar(claudio);
    }
    public static void hacerCantar(PuedeCantar cantor) {
        cantor.cantar();
    }
}

Ejercicio 2.
Algunos seres pueden caminar y puede nadar estas dos capacidades son interfases (PuedeCaminar.java y PuedeNadar.java).
Los mamiferos son animales que pueden moverse (Mamifero.java). El gato es un mamifero que puede nadar y moverse (Gato.java).
Un Loro puede caminar pero no puede nadar.

PuedeCaminar.java

public interface PuedeCaminar{
    public void caminar();
}
PuedeNadar.java
public interface PuedeNadar {
    public void nadar();
}
Mamifero.java
public class Mamifero {
    String especie, color;
    public void caminar() {
        System.out.println("El mamífero camina");
    }
}
Gato.java
public class Gato extends Mamifero implements PuedeCaminar, PuedeNadar {
    private int numeroPatas = 4;
    public void nadar() {
        System.out.println("El gato nada");
    }
}

Loro.java
public class Loro implements PuedeCaminar...
    ...System.out.println("El loro camina");
    ...

Interfaces.java
public class Interfaces {
    public static void main(String[] args) {
        Gato felix = new Gato();
        felix.caminar();
        felix.nadar();
        Loro pepe = new Loro();
        pepe.caminar();
    }
}

Por que no se requiere escribir todos los métodos de las interfaces en la clase Gato?
Ejercicio adicional.
Agregue al ejercicio anterior la interface PuedeVolar.java
Agregue la superclase Aves.java
Herede la clase Avestruz.java (ave que solo camina)
Herede la clase Loro.java (ave que camina y vuela)
Herede la clase Murciélago.java (es un mamífero que vuela y camina)
Cree la clase Felino.java (es un mamifero que camina y puede nadar).
Modifique la clase Gato.java (es un Felino)
Cree la clase Tigre.java

3. FECHAS Y NUMEROS
3.1. Calendar
package java.util.*
public abstract class Calendar
extends Object
implements Serializable, Cloneable

Calendar es un clase abstracta para obtener de un dato tipo fecha, datos enteros como YEAR, MONTH, DAY, HOUR, entre otros.
(Un objeto Date representa un instante especifico de tiempo con presicion de milisegundos.)
Las susclases de Calendar interprestan un Date de acuerdo a las reglas de un calendario. Java provee la subclase GregorianCalendar.
Estan pendientes de desarrollar otros calendarios.
La clase Calendar provee una método de clase llamado getInstance que retorna un objeto inicializado con la fecha y hora actual.

TestCalendar.java

import java.util.*;
public class TestCalendar {
public static void main(String[] args) {
    // Obtener la fecha actual
    Calendar cal = Calendar.getInstance();
    // Obtener los componentes de la fecha.
    int era = cal.get(Calendar.ERA); // 0=BC, 1=AD
    int year = cal.get(Calendar.YEAR); // 2002
    int month = cal.get(Calendar.MONTH); // 0=Ene, 1=Feb, ...
    int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
    int weekOfMonth = cal.get(Calendar.WEEK_OF_MONTH);
    int day = cal.get(Calendar.DAY_OF_MONTH); // 1...
    int dayOfYear = cal.get(Calendar.DAY_OF_YEAR); //
    int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); //1=Domingo,2=Lunes...
    int dayOfWeekInMonth = cal.get(Calendar.DAY_OF_WEEK_IN_MONTH);
    System.out.println("ERA: " + era);
    System.out.println("YEAR: " + year);
    System.out.println("MONTH: " + month);
    System.out.println("WEEK_OF_YEAR: " + weekOfYear);
    System.out.println("WEEK_OF_MONTH: " + weekOfMonth);
    System.out.println("DAY_OF_MONTH: " + day);
    System.out.println("DAY_OF_YEAR: " + dayOfYear);
    System.out.println("DAY_OF_WEEK: " + dayOfWeek);
    System.out.println("DAY_OF_WEEK_IN_MONTH: "+dayOfWeekInMonth);
    // Obtener hora actual
    int ampm = cal.get(Calendar.AM_PM); // 0=am 1=pm
    int hour = cal.get(Calendar.HOUR); // 0..23
    int hourOfDay = cal.get(Calendar.HOUR_OF_DAY);
    int minute = cal.get(Calendar.MINUTE); // 0..60
    int second = cal.get(Calendar.SECOND); // 0..60
    int miliSecond = cal.get(Calendar.MILLISECOND);
    System.out.println("AM_PM: " + ampm );
    System.out.println("HOUR: " + hour);
    System.out.println("HOUR_OF_DAY: " + hourOfDay);
    System.out.println("MINUTE: " + minute);
    System.out.println("SECOND: " + second);
    System.out.println("MILLISECOND: " + miliSecond);
    }
}

3.2. GregorianCalendar
package java.util.*
public class GregorianCalendar
extends Calendar
La clase GregorianCalendar es una subclase de Calendar y maneja el calendario estandar usado en el mundo.

TestGregorianCalendar.java
import java.util.*;
public class TestGregorianCalendar {

    public static void main(String[] args) {

        //Que dia de la semana es navidad
        Calendar xmas = new GregorianCalendar(2005, Calendar.DECEMBER, 25);
        int dayOfWeek = xmas.get(Calendar.DAY_OF_WEEK);
        System.out.println("Dia (1=Domingo): " + dayOfWeek );

        //Cuantos dias tuvo febrero de 2005
        Calendar feb = new GregorianCalendar(2005, Calendar.FEBRUARY, 1);
        int days = feb.getActualMaximum(Calendar.DAY_OF_MONTH);
        System.out.println("dias en Feb 2005: " + days );

        //Cuantos dias tuvo febrero de 2000
        Calendar cal = new GregorianCalendar(2000, Calendar.FEBRUARY, 1);
        days = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        System.out.println("dias en Feb 2000: " + days );

        //Determinar cual fue primero navidad o febrero
        boolean after = xmas.after(feb);
        boolean before = xmas.before(feb);

        System.out.println("xmas.after(feb): " + after );
        System.out.println("xmas.before(feb): " + before );
        //Obtener la diferencia en milisegundos
        long diffMillis = xmas.getTimeInMillis() - feb.getTimeInMillis();

        //Obtener la diferencia en segundos
        long diffSecs = diffMillis/1000;

        //Obtener la diferencia en minutos
        long diffMins = diffSecs/60;

        //Obtener la diferencia en horas
        long diffHours = diffMins/60;

        //Obtener la diferencia en dias
        long diffDays = diffHours/24;
        //Obtener la diferencia en meses
        long diffMonths = diffDays/30;

        System.out.println("diffMillis: " + diffMillis );
        System.out.println("diffSecs: " + diffSecs );
        System.out.println("diffMins: " + diffMins );
        System.out.println("diffHours: " + diffHours );
        System.out.println("diffDays: " + diffDays );
        System.out.println("diffMonths: " + diffMonths );
    }
}

3.3. SimpleDateFormat
public class SimpleDateFormat
extends DateFormat
SimpleDateFormat es una clase para formatear y parsear fechas permitiendo convetir datos fechas en texto y viceversa.

TestDateFormater.java
import java.text.*;
import java.util.*;
public class TestDateFormater {

    public static void main(String[] args)
    throws Exception
    {
        //Fecha -> String
        Calendar now = new GregorianCalendar();
        SimpleDateFormat name, standar;
        String nameFormat, standarFormat;

        //Obtener la fecha actual en un calendario
        Date nowDate = now.getTime();

        //Definimos dos formatos para mostrar fechas
        name = new SimpleDateFormat("EEEE, dd MMMM yyyy");
        standar = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        //Aplicamos el formato a la fecha actual.
        nameFormat = name.format( nowDate );
        standarFormat = standar.format( nowDate );

        System.out.println(nameFormat);
        System.out.println(standarFormat);

        //Aplicamos un formato en otro idioma.
        name = new SimpleDateFormat("EEEE, dd MMMM yyyy", Locale.FRENCH);

        nameFormat = name.format(nowDate);

        System.out.println(nameFormat);
        //String -> Fecha
        Calendar cal = new GregorianCalendar();
        SimpleDateFormat format;

        //Definimos un formato
        format = new SimpleDateFormat("dd/MM/yyyy");
        //Se realiza parse al texto en base al formato
        Date calDate = format.parse("25/12/2005");

        //Se asigna la fecha al calendario.
        cal.setTime( calDate );

        int dayOfYear = cal.get(Calendar.DAY_OF_YEAR);
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
        System.out.println("DAY_OF_YEAR: " + dayOfYear);
        System.out.println("DAY_OF_WEEK: " + dayOfWeek);
    }
}

3.4. NumberFormat
public abstract class NumberFormat
extends Format
NumberFormat es una clase abstracta para formatear numeros permitiendo que el código sea independiente de las convenciones propias de cada pais.

TestNumberFormat.java
import java.text.*;
import java.util.*;
public class TestNumberFormat {

    public static void main(String[] args) {

        //Locale.setDefault(Locale.CANADA);

        //El simbolo 0 muestra un cero cuando no exista un digito.
        NumberFormat formatter = new DecimalFormat("000000");
        String s = formatter.format(-1234.567); // -001235
        System.out.println("000000 : "+s);
        //notese que el numero se ha redondeado

        //El simbolo # muestra un digito nada sino existe un digito
        formatter = new DecimalFormat("##");
        s = formatter.format(-1234.567); // -1235
        System.out.println("## : "+s);
        formatter = new DecimalFormat("##00");
        s = formatter.format(0); // 00
        System.out.println("##00 : "+s);

         //El simbolo . muestra el punto decimal
         formatter = new DecimalFormat(".00");
         s = formatter.format(-.567); // -.57
         System.out.println(".00 : "+s);
         formatter = new DecimalFormat("0.00");
         s = formatter.format(-.567); // -0.57
         System.out.println("0.00 : "+s);
         formatter = new DecimalFormat("#.#");
         s = formatter.format(-1234.567); // -1234.6
         System.out.println("#.# : "+s);
         formatter = new DecimalFormat("#.######");
         s = formatter.format(-1234.567); // -1234.567
         System.out.println("#.###### : "+s);
         formatter = new DecimalFormat(".######");
         s = formatter.format(-1234.567); // -1234.567
         System.out.println(".###### : "+s);
         formatter = new DecimalFormat("#.000000");
         s = formatter.format(-1234.567); // -1234.567000
         System.out.println("#.000000 : "+s);

         //El simbolo , se usa para agrupar numeros

formatter = new DecimalFormat("#,###,###");
s = formatter.format(-1234.567); // -1,235
System.out.println("#,###,### : "+s);
s = formatter.format(-1234567.890); // -1,234,568
System.out.println("#,###,### : "+s);
    }
}

Ejercicios con fechas y números
1. Muestre su edad en años, meses, días, horas, minutos, segundos.
2. Muestre cuantos dias faltan para navidad.
3. Cree un formato para un número de acuerdo a su cantidad de dígitos.
4. Muestre en formato texto el día de semana que nació.