martes, 16 de febrero de 2021

Recursión

Un método recursivo es aquel que, en el cuerpo del mismo, se invoca a sí mismo. Ejemplo de aplicaciones: Examinar todos los ficheros de un directorio examinando a su vez todos los ficheros de sus subdirectorios. Buscar el significado de una palabra de un diccionario. Es una herramienta muy potente y peligrosa. Ej. obtener la suma de n y los n-1 numeros anteriores a n: public static long suma(long n) { long s = 0; //caso base n = 1 if (n == 1) return s= 1; else return s= suma(n-1)+n; } Se debe tener siempre un caso base que se resuelva sin recursión. El caso general debe ir acercándose paso a paso al caso base, sin pasarse. //Otro ej.Imprime un entero en cualquier base entre 2 y 16. public static final String tablaDigitos = "0123456789abcdef"; public static final int maxBase = tablaDigitos.length(); //Metodo recursivo: public static void imprimeEnteroEnCualquierBase(int n, int b) { if(n>=b) imprimeEnteroEnCualquierBase( n/b, b); System.out.print(tablaDigitos.charAt(n%b)); } //Metodo guia: public static void imprimeEntero(int n, int b){ if(b<=1 || b > maxBase) System.err.println("Base no correcta. "+b); else if (n<0) { n=-n; System.out.println("ha puesto un numero negativo"); } imprimeEnteroEnCualquierBase(n,b); }

sábado, 6 de febrero de 2021

Estructuras de datos lineales.

Estructuras de datos lineales: Se llaman tipos de datos lineales los que estan formados por secuencias de datos de un mismo tipo. Se distinguen tres tipos de linealidades o secuencias: pilas, colas y listas con puntos de interés. Estas estructuras de datos lineales se pueden implementar con arrays o con elementos enlazados, que ahora explicaremos. Con arrays: los elementos de la secuencia se disponen sucesivamente en los distintos componentes de un array lo suficientemente grande para que quepan e incluso sobren componentes, de modo que si el tamaño del array es m, en numero de elementos de la secuencia introducidos sean n, de modo que n <= m; Con elementos enlazados -secuencias enlazadas-. Vamos a estudiar como se implementa una secuencia enlazada: Un elemento u objeto de una secuencia enlazada es un objeto muy abstracto, consta de dos variables una que puede ser valores de cualquier tipo de dato, siempre del mismo tipo, y la siguiente variable que forma parte del Nodo, que así se llama el elemento de la secuencia, es un dato que contiene la referencia o direccion de memoria del heap, del nodo previamente creado. NODO:la clase Nodo. Es la estructura mínima, elemental, un solo objeto de una secuencia. Consta de un dato del tipo que sea (int, double, String, twit, ... ) eso sí, todos serán del mismo tipo. Y de otro dato donde se guarda la referencia que tiene en el heap el nodo anterior. Sea la clase NodoInt -nodos con datos de enteros. Sus atributos estan formado, como hemos dicho, por dos valores, uno un dato entero y otro por un dato que es la referencia de la memoria del nodo anterior. (Al implementar la clase, esta primera refenrcia no existirá, pues el primer nodo no contendrá, en su doto referencia correspondiente, el valor de ningun otro nodo, por ser este el primero. Pero a partir del segundo, en este atributo, se guardarán las referencias de los anteriores; veamos: public class NodoInt{ private int dato; private NodoInt sec; public NodoInt(int d){ this.dato = d; this.sec = null; } public NodoInt(int d,NodoInt sec){ this.dato = d; this.sec = sec; } public static void main(String[] arg){ NodoInt sec = null; sec = new NodoInt(10); sec = new NodoInt(20,sec); sec = new NodoInt(30,sec); sec = new NodoInt(40,sec); sec = new NodoInt(50,sec); sec = new NodoInt(60,sec); sec = new NodoInt(70,sec); //imprimir(sec); //saturar(60,sec); //buscar(30,sec); //buscar(sec,4);//Este método, que tiene el mismo nombre que el anterior, al cambiar los parametros formales, //está implementado de forma distinta: obtiene el valor de d en un nodo iésimo. //cambiar(30,10000,sec); insercion(sec,25); } //podemos ir implementando los métodos de recorridos, búsquedas, inserción, eliminación, ... que consideremos oportunos para manipular la secuencia enlazada. public static void imprimir(NodoInt sec){ NodoInt aux = sec; while(aux!=null){ System.out.println(aux.dato); aux=aux.sec; } } public static void saturar(int n,NodoInt sec){ NodoInt aux = sec; while(aux!=null){ if(aux.dato>n)aux.dato=n; System.out.println(aux.dato); aux = aux.sec; } } public static void buscar(int n, NodoInt sec){ NodoInt aux = sec; while(aux!=null&&aux.dato!=n){ aux = aux.sec; } System.out.println(aux.dato); } public static int buscar(NodoInt sec,int i){ NodoInt aux = sec; int k =0; while(aux!=null&&k=d: while (aux!=null &&aux.dato

martes, 2 de febrero de 2021

Excepciones.

Hemos dicho que hay tres tipos de errores en programación: errores que se detectan al compilar, por lo que se corrigen inmediatamente; errores de ejecución, que producen una ruptura en la ejecución del programa; y errores lógicos, que son indetectables, y producen resultados falsos e imprevisibles. Los que pueden tener un tratamiento de entre los errores de ejecución son los llamados excepciones, en cambio, los llamados propiamente errores, no tienen tratamiento. Los errores y excepciones -errores de ejecución- generan al producirse objetos de la clase específica de ese error. Nosotros estudiaremos los de las subclases de Exception, pues son recuperables.
Nos centraremos, de entre la clase exception, en las IOException y RuntimeException. LANZAR UNA EXCEPCIÓN. Cuando se produce un error de ejecución, el ordenador lanza una excepción, un objeto de una clase, y se interrumpe su ejecución. El programador puede también provocar el lanzamiento de una excepción, con la instrucción throw e; siendo e un objeto de la clase de excepción que interese. Ej: Scanner t= new Scanner(System.in); System.out.println("Introduzca la hora, -entre 0 y 23-"); int h = t.nextInt(); if (h < 0 || h>23){ throw new InputMismatchException( "Valor incorrecto "); } El ordenador lanza una excepción, bien de modo propio, bien provocada por el programador. El siguiente paso es CAPTURA DE LA EXCEPCIÓN: Si no se gestiona la excepción lanzada se produce una terminación abrupta del programa. Java dispone de una instrucción que permite gestionar las excepciones lanzadas: try-catch o try-catch-finally. Con esta instrucción se CAPTURA la excepción del tipo, y se continúa la ejecución del programa como se desee. Ejemplo: try { código donde se pueden producir excepciones } catch(TipoExcepcion1 e1){ lo que se hace con ello } catch(TipoExcepcion2 e2){ lo que se hace con ello } .. finally { bloque opcional. Se ejecuta siempre, tanto si se han producido excepciones como si no. } Hemos visto hasta ahora que errores de ejecución lanzan excepciones, que también el programador puede producir el lanzamiento de excepciones como la instrucción throw e, el tipo de excepción. Hemos visto así mismo como se capturan con la instrucción try-catch: try como el bloque matriz donde se genera la excepción y catch que captura propiamente la excepción de un tipo concreto. .. puede haber tantos catchs como tipos distintos de excepciones se puedan generar. Vamos a ver la PROPAGACIÓN de excepciones: tratar la excepción en un lugar distinto de donde se ha producido. Java permite añadir cláusulas en las cabeceras de los métodos para que se propaguen las excepciones que se generen en su interior. Esta cláusula es throws TipoException, pudiendo haber más de una excepción, separadas con comas. Ejemplo: public static void escribeComp(int i, int[] a) throws ArrayIndexOutOfBoundsException { System.out.println(a[i]); } public static void main(String args[]){ int [] v = new int[100]; Scanner t = new Scanner(System.in); boolean lecturaCorrecta = false; int n = 0; do { try { System.out.print("Índice (entre 0 y 99)? "); n = t.nextInt(); escribeComp(n,v);//puede dar la excepción de fuera de rango lecturaCorrecta = true; } catch (ArrayIndexOutOfBoundsException e) { System.out.println("error, "+ n +" incorrecto, pruebe otra vez. "); } while(!lecturaCorrecta); } si llega aquí es que ha hecho una lectura correcta! el while lo que hace es que se repita la entrada si la lectura no ha sido correcta, pues el valor de la guarda es true: niega una negación. y mientras la guarda sea true repite el bucle. ds del método y antes del bloque de instruccione, pone el try-catch en el do!

domingo, 5 de enero de 2020

La clase Container es una clase abstracta derivada de Component, que representa a cualquier componente que pueda contener otros componentes. Se trata, en esencia, de añadir a la clase Component la funcionalidad de adición, sustracción, recuperación, control y organización de otros Componentes.
Al igual que la clase Component, no dispone de constructores públicos y, por lo tanto, no se pueden instanciar objetos de la clase Container. Sin embargo, sí se puede extender para implementar la nueva característica incorporada a Java en el JDK 1.1, de los componentes Lightweight.
El AWT proporciona varias clases de Contenedores:
  • Panel
    • Applet
  • ScrollPane
    • Window
    • Dialog
      • FileDialog
    • Frame
Aunque los que se pueden considerar como verdaderos Contenedores con WindowFrameDialog y Panel, porque los demás son subtipos con algunas características determinadas y solamente útiles en circunstancias muy concretas.
Window
Es una superficie de pantalla de alto nivel (una ventana). Una instancia de la clase Window no puede estar enlazada o embebida en otro Contenedor.
El controlador de posicionamiento de Componentes por defecto, sobre un objeto Window, es el BorderLayout.
Una instancia de esta clase no tiene ni título ni borde, así que es un poco difícil de justificar su uso para la construcción directa de un interfaz gráfico, porque es mucho más sencillo utilizar objetos de tipo Frame o Dialog. Dispone de varios métodos para alterar el tamaño y título de la ventana, o los cursores y barrar de menús.
Frame
Es una superficie de pantalla de alto nivel (una ventana) con borde y título. Una instancia de la clase Frame puede tener una barra de menú. Una instancia de esta clase es mucho más aparente y más semejante a lo que se entiende por ventana.
Y, a no ser que el lector haya comenzado su estudio por esta página, ya se habrá encontrado en varias ocasiones con la clase Frame, que es utilizada en gran parte de los ejemplos de este Tutorial. Su uso se debe en gran parte a la facilidad de su instanciación y, lo que tampoco deja de ser interesante, su facilidad de conclusión.
La clase Frame extiende a la clase Window, y su controlador de posicionamiento de Componentes por defecto es el BorderLayout.
Los objetos de tipo Frame son capaces de generar varios tipos de eventos, de los cuales el más interesante es el evento de tipo WindowClosing, que se utiliza en este Tutorial de forma exhaustiva, y que se produce cuando el usuario pulsa sobre el botón de cerrar colocado en la esquina superior-derecha (normalmente) de la barra de título del objeto Frame.
En el ejemplo java1312.java se ilustra el uso de la clase Frame y algunos de sus métodos. El programa instancia un objeto Frame con tres botones que realizan la acción que se indica en su título. La imagen reproduce la ventana que genera la aplicación y su situación tras haber pulsado el botón que cambia el cursor a forma de mano.
Es un ejemplo muy simple, aunque hay que advertir al lector que se hace uso en él de la sintaxis abreviada de las clases anidadas, que se tratarán en otra sección; para que no se asuste al ver el código del ejemplo. Este método se utiliza para instanciar y registrar receptores de eventos sobre los tres botones, más el de cerrar la ventana, colocados sobre el objeto Frame.
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class java1312 {
    public static void main( String args[] ) {
        IHM ihm = new IHM();
        }
    }

class IHM {
    Frame miFrame;

    public IHM() {
        // Se instancian tres botones con textos indicando lo que
        // hacen cuando se pulse sobre ellos
        Button botonTitulo = new Button( "Imprime Titulo" );
        Button botonCursorMano = new Button( "Cursor Mano" );
        Button botonCursorFlecha = new Button( "Cursor Flecha" );

        // Instancia un objeto Frame con su titulo indicativo de que se
        // se trata, utilizando un FlowLayout
        miFrame = new Frame( "Tutorial de Java, AWT" );
        miFrame.setLayout( new FlowLayout() );

        // Añade tres objetos Button al Frame
        miFrame.add( botonTitulo );
        miFrame.add( botonCursorMano );
        miFrame.add( botonCursorFlecha );

        // Fija el tamaño del Frame y lo hace visible
        miFrame.setSize( 250,200 );
        miFrame.setVisible( true );    

        // Instancia y registra objetos ActionListener sobre los
        // tres botones utilizando la sintaxis abreviada de las
        // clases anidadas
        botonTitulo.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent evt ) {
                System.out.println( miFrame.getTitle() );
                }
            } );

        botonCursorMano.addActionListener( new ActionListener() {
            public void actionPerformed(ActionEvent evt ) {
                miFrame.setCursor( new Cursor( Cursor.HAND_CURSOR ) );
                }
            } );

        botonCursorFlecha.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent evt ) {
                miFrame.setCursor( new Cursor( Cursor.DEFAULT_CURSOR ) );
                }
            } );

        // Instancia y registra un objeto WindowListener sobre el objeto
        // Frame para terminar el programa cuando el usuario haga click
        // con el raton sobre el boton de cerrar la ventana que se 
        // coloca sobre el objeto Frame
        miFrame.addWindowListener( new WindowAdapter() {
            public void windowClosing( WindowEvent evt ) {
                // Concluye la aplicacion cuando el usuario cierra la 
               // ventana
                System.exit( 0 );
                }
            } );
        }
    }
El siguiente trozo de código es el típico utilizado en la instanciación de un objeto Frame, la indicación del controlador de posicionamiento de Componentes que se va a utilizar y, en este caso, la incorporación de los tres Componentes de tipo Button al objeto Frame.
// Se instancian tres botones con textos indicando lo que
// hacen cuando se pulse sobre ellos
Button botonTitulo = new Button( "Imprime Titulo" );
Button botonCursorMano = new Button( "Cursor Mano" );
Button botonCursorFlecha = new Button( "Cursor Flecha" );

// Instancia un objeto Frame con su titulo indicativo de que se
// se trata, utilizando un FlowLayout
miFrame = new Frame( "Tutorial de Java, AWT" );
miFrame.setLayout( new FlowLayout() );

// Añade tres objetos Button al Frame
miFrame.add( botonTitulo );
miFrame.add( botonCursorMano );
miFrame.add( botonCursorFlecha );
Y en los dos bloques de sentencias que se reproducen a continuación, se utilizan clases anidadas para instanciar y registrar objetos de tipo ActionListener. Por ejemplo, sobre el botón que permite recoger el título de la ventana, se hace tal como se indica.
botonTitulo.addActionListener( new ActionListener() {
    public void actionPerformed( ActionEvent evt ) {
        System.out.println( miFrame.getTitle() );
        }
    } );
Y, para instanciar y registrar un objeto WindowListener sobre el objeto Frame, para concluir la aplicación cuando el usuario cierre la ventana, se emplean las siguientes líneas de código.
miFrame.addWindowListener( new WindowAdapter() {
    public void windowClosing( WindowEvent evt ) {
        // Concluye la aplicación cuando el usuario cierra la 
        // ventana
        System.exit( 0 );
        }
    } );
Dialog
Es una superficie de pantalla de alto nivel (una ventana) con borde y título, que permite entradas al usuario. La clase Dialog extiende la clase Window, que extiende la clase Container, que extiende a la clase Component; y el controlador de posicionamiento por defecto es el BorderLayout.
De los constructores proporcionados por esta clase, destaca el que permite que el diálogo sea o no modal. Todos los constructores requieren un parámetro Frame y, algunos de ellos, permiten la especificación de un parámetro booleano que indica si la ventana que abre el diálogo será modal o no. Si es modal, todas las entradas del usuario serán recogidas por esta ventana, bloqueando cualquier entrada que se pudiese producir sobre otros objetos presentes en la pantalla. Posteriormente, si no se ha especificado que el diálogo sea modal, se puede hace que adquiera esta característica invocando al método setModal().
El ejemplo java1313.java, cuya imagen en pantalla al arrancar es la que reproduce la imagen que precede a este párrafo, presenta el mínimo código necesario para conseguir que un objeto Dialog aparezca sobre la pantalla. Cuando se arranca el programa, en la pantalla se visualizará un objeto Frame y un objeto Dialog, que debería tener la mitad de tamaño del objeto Frame y contener un título y un botón de cierre. Este botón de cierre no es operativo. El objeto Dialog no tiene la caja de control de la esquina superior izquierda al uso.
El objeto Dialog puede ser movido y redimensionado, aunque no se puede ni minimizar ni maximizar. Se pueden colocar en cualquier lugar de la pantalla, su posición no está restringida al interior del padre, el objeto Frame.
El objeto Dialog difiere significativamente en apariencia del objeto Frame, sobre todo por la presencia del borde en este último, circunstancia que llama mucho la atención.
import java.awt.*;
import java.awt.event.*;

public class java1313 extends Frame {
    public static void main( String args[] ) {
        // Instancia un objeto de este tipo
        new java1313();
        }

    // Constructor
    public java1313() {
        setTitle( "Tutorial de Java, AWT" );  
        setSize( 250,150 );
        setVisible( true );

        Dialog miDialogo = new Dialog( this,"Dialogo" );
        miDialogo.setSize( 125,75 );
        // Hace que el dialogo aparezca en la pantalla
        miDialogo.show();
        }
    }
La parte más interesante del ejemplo reside en tres sentencias. La primera, instancia el objeto Dialog como hijo del objeto principal, this . La segunda sentencia establece el tamaño inicial del objeto Dialog. La tercera sentencia hace que el objeto Dialog aparezca en la pantalla.
Dialog miDialogo = new Dialog( this,"Dialogo" );
miDialogo.setSize( 125,75 );
// Hace que el dialogo aparezca en la pantalla
miDialogo.show();
El ejemplo java1314.java, está diseñado para producir dos objetos Dialog, uno modal y otro no-modal. Un objeto Frame sirve de padre a los dos objetos Dialog.
El Dialog no-modal se crea con un botón que sirve para cerrarlo. Sobre este botón se instancia y registra un objeto ActionListener. Este objeto ActionListener es instanciado desde una clase ActionListener compartida. El código del método sobrescrito actionPerformed() de la clase ActionListener, cierra el objeto Dialog, invocando al método setVisible() con el parámetro false , aunque también se podría haber utilizado hide() o dispose().
El Dialog modal se crea de la misma forma, conteniendo un botón al que se asigna un cometido semejante.
Sobre el objeto Frame se crean dos botones adicionales, uno mostrará el diálogo modal y el otro mostrará el diálogo no-modal. Estos dos objetos Button comparten una clase ActionListener que está diseñada para mostrar un objeto Dialog de un tamaño predeterminado y en una posición parametrizada, controlada a través del parámetro offset, que se pasa al objeto ActionListener cuando se instancia.
La imagen muestra la ventana que genera la aplicación cuando se ejecuta por primera vez y se selecciona el Diálogo No-Modal, pulsando el botón correspondiente.
Para evitar que se superpongan, los objetos ActionListener de los dos botones que visualizan los objetos Dialog, se instancian con valores de offset diferentes, por lo que aparecerán en posiciones distintas de la pantalla en el momento de su visualización.
Si se compila y ejecuta el programa, aparecerán los dos botones en la pantalla, tal como muestra la imagen que aparece en párrafos anteriores. Uno de los botones puede ser utilizado para mostrar el objeto Dialog no-modal y el otro para visualizar el Dialog modal. Cuando el objeto Dialog modal no está visible, se podrá mostrar y cerrar el objeto Dialog no-modal, o pulsar en la caja de cierre del Frame para terminar la ejecución del programa. Sin embargo, cuando está visible el Dialog modal, no se podrá realizar ninguna otra acción dentro del programa; el modo de operación es el que se conoce como aplicación modal.
Un objeto receptor de eventos windowClosing() es instanciado y registrado sobre el Frame para concluir la ejecución del programa cuando se cierre el Frame; sin embargo, el Frame no puede cerrarse cuando el objeto Dialog modal está visible.
A continuación se comentan los trozos de código más interesantes del ejemplo anterior. El primero de ellos es la sentencia que instancia el objeto Frame, que a pesar de ser semejante a muchas de las ya vistas, lo que la hace importante en este programa es el ser padre de los dos objetos Dialog, por lo cual es imprescindible que sea instanciado antes de los dos objetos Dialog.
Frame miFrame = new Frame( "Tutorial de Java, AWT" );
El siguiente fragmento interesante es el típico código que es utilizado para instanciar los objetos Dialog, colocar un objeto Button en el objeto Dialog, e instanciar y registrar un objeto ActionListener sobre el objeto Button.
Dialog dialogoNoModal = new Dialog( miFrame,"Dialogo No Modal" );
Button botonCerrarNoModal = new Button( "Cerrar" );
dialogoNoModal.add( botonCerrarNoModal );
botonCerrarNoModal.addActionListener(
    new closeDialogListener( dialogoNoModal ) );
Este es el fragmento que crea el objeto Dialog modal. El que se usa para crear el objeto Dialog no-modal es esencialmente el mismo excepto que no tiene el parámetro booleando true en la invocación del constructor.
Este código es seguido por el que instancia los objetos Button y registra objetos ActionListener sobre estos botones. Y, a este código le sigue el que finaliza la construcción del objeto Frame, que ya se ha visto en varias ocasiones y no merece la pena insistir en él.
El trozo de código más interesante de todos es el fragmento en que la clase ActionListener es utilizada para instanciar objetos para mostrar un objeto Dialog. Y es muy interesante por dos aspectos. Uno de ellos es el constructor parametrizado que se utiliza para guardar el offset que se le pasa como parámetro al objeto ActionListener, cuando se instancia. Este valor de offset es combinado con valores en el código para controlar el tamaño y la posición del objeto Dialog cuando aparece en la pantalla. El otro aspecto interesante es que el método show() de la clase Dialog es utilizado para hacer aparecer el objeto Dialog en la pantalla.
class showDialogListener implements ActionListener {
    Dialog oDialog;
    int oOffset;

    showDialogListener( Dialog dialogo,int offset ) {
        oDialog = dialogo;
        oOffset = offset;
        }

    public void actionPerformed( ActionEvent evt ) {
        // Seguir este orden es critico para un dialogo modal
        oDialog.setBounds( oOffset,oOffset,150,100 );
        oDialog.show();    
        }
    }
El orden de ejecución de las sentencias dentro del método actionPerformed() es crítico. Si el método show() se ejecuta antes del método setBounds() sobre el objeto Dialog modal, el método setBounds() utilizado para controlar el tamaño y posición del objeto Dialog, no tendría efecto alguno. Tamaño y posición del diálogo deben establecerse antes de hacerlo visible.
El último fragmento de código interesante es el método sobrescrito actionPerformed() utilizado para cerrar los objetos Dialog. En este ejemplo se usa la llamada al método setVisible() con el parámetro false, aunque también se podría haber utilizado el método hide() o el método dispose(), con el mismo cometido.
public void actionPerformed( ActionEvent evt ) {
    oDialog.setVisible( false );
    }
Panel
La clase Panel es un Contenedor genérico de Componentes. Una instancia de la clase Panel, simplemente proporciona un Contenedor al que ir añadiendo Componentes.
El controlador de posicionamiento de Componentes sobre un objeto Panel, por defecto es el FlowLayout; aunque se puede especificar uno diferente en el constructor a la hora de instanciar el objeto Panel, o aceptar el controlador de posicionamiento inicialmente, y después cambiarlo invocando al método setLayout().
Panel dispone de un método addNotify(), que se utiliza para crear un observador general (peerPerr) del Panel. Normalmente, un Panel no tiene manifestación visual alguna por sí mismo, aunque puede hacerse notar fijando su color de fondo por defecto a uno diferente del que utiliza normalmente.
El ejemplo java1315.java, ilustra la utilización de objetos Panel para configurar un objeto de tipo interfaz gráfica, o interfaz hombre-máquina, incorporando tres objetos Panel a un objeto Frame.
El controlador de posicionamiento de los Componentes para el objeto Frame se especifica concretamente para que sea un FlowLayout, y se alteran los colores de fondo de los objetos Panel para que sean claramente visibles sobre el Frame. Sobre cada uno de los paneles se coloca un objeto, utilizando el método add(), de tal modo que se añade un objeto de tipo campo de texto sobre el Panel de fondo amarillo, un objeto de tipo etiqueta sobre el Panel de fondo rojo y un objeto de tipo botón sobre el Panel de fondo azul.
Ninguno de los Componentes es activo, ya que no se instancian ni registran objetos receptores de eventos sobre ellos. Así, por ejemplo, el único efecto que se puede observar al pulsar el botón del panel azul, se limita al efecto visual de la pulsación. Sin embargo, sí se instancia y registra un receptor de eventos sobre el Frame, para recoger la intención del usuario de cerrar la ventana y terminar la ejecución de la aplicación.
import java.awt.*;
import java.awt.event.*;

public class java1315 {
    public static void main( String args[] ) {
        IHM ihm = new IHM();
        }
    }

class IHM {
    public IHM() {
        // Se construyen tres Paneles con fondos de color diferente
        // y sin contener ningun elemento activo
        Panel panelIzqdo = new Panel();
        panelIzqdo.setBackground( Color.yellow );
        panelIzqdo.add( new TextField( "Panel Izquierdo -> amarillo" ) );

        Panel panelCentral = new Panel();
        panelCentral.setBackground( Color.red );
        panelCentral.add( new Label( "Panel Central -> rojo" ) );

        Panel panelDrcho = new Panel();
        panelDrcho.setBackground( Color.blue );
        panelDrcho.add( new Button( "Panel Derecho -> azul" ) );

        // Se instancia un objeto Frame utilizando un FlowLayout y
        // se colocan los tres objetos Panel sobre el Frame
        Frame miFrame = new Frame( "Tutorial de Java, AWT" );
        miFrame.setLayout( new FlowLayout() );

        miFrame.add( panelIzqdo );
        miFrame.add( panelCentral );
        miFrame.add( panelDrcho );    
        miFrame.setSize( 500,200 );
        miFrame.setVisible( true );

        miFrame.addWindowListener( new Conclusion() );
        }
    }

class Conclusion extends WindowAdapter {
    public void windowClosing( WindowEvent evt ) {
        // Concluye la aplicacion cuando el usuario cierra la ventana
        System.exit( 0 );
        }
    }
Las sentencias de código más interesantes del ejemplo se limitan a la típica instanciación de los tres objetos Panel, al control del color de fondo y a la incorporación de otro Componente al Panel, tal como se reproduce en las siguientes sentencias.
Panel panelIzqdo = new Panel();
panelIzqdo.setBackground( Color.yellow );
panelIzqdo.add( new TextField( "Panel Izquierdo -> amarillo" ) );
Las siguientes líneas de código instancian un objeto Frame y le añaden los tres objetos Panel construidos anteriormente.
Frame miFrame = new Frame( "Tutorial de Java, AWT" );
miFrame.setLayout( new FlowLayout() );

miFrame.add( panelIzqdo );
miFrame.add( panelCentral );
miFrame.add( panelDrcho );
Con este trozo de código se genera el objeto de más alto nivel de la aplicación para el interfaz de usuario.
Añadir Componentes a un Contenedor
Para que un interfaz sea útil, no debe estár compuesto solamente por Contenedores, éstos deben tener Componentes en su interior. Los Componentes se añaden al Contenedor invocando al método add() del Contenedor. Este método tiene tres formas de llamada que dependen del manejador de composición o layout manager que se vaya a utilizar sobre el Contenedor.
En el código siguiente, java1316.java, se incorporan dos botones al Contenedor de tipo Frame. La creación se realiza en el método init() porque éste siempre es llamado automáticamente al inicializarse el applet. De todos modos, al inciarse la ejecución se crean los botones, ya que el método init() es llamado tanto por el navegador como por el método main().
import java.awt.*;

public class java1316 extends java.applet.Applet {

    public void init() {
        add( new Button( "Uno" ) );
        add( new Button( "Dos" ) );
        }

    public static void main( String args[] ) {
        Frame f = new Frame( "Tutorial de Java" );
        java1316 ejemplo = new java1316();

        ejemplo.init();

        f.add( "Center",ejemplo );
        f.pack();
        f.show();
        }
    }
El ejemplo también muestra la forma de cómo el código puede ejecutarse tanto como aplicación, utilizando el intérprete de Java, como desde un navegador, funcionando como cualquiera de los applets que se han visto en ejemplos anteriores. En ambos casos el resultado, en lo que al ejemplo se refiere, es el mismo: aparecerán dos botones en el campo delimitado por el Contenedor Frame.
Los Componentes añadidos a un objeto Container entran en una lista cuyo orden define el orden en que se van a presentar los Componentes sobre el Contenedor, de atrás hacia delante. Si no se especifica ningún índice de orden en el momento de incorporar un Componente al Contenedor, ese Componente se añadirá al final de la lista. Hay que tener esto muy en cuenta, sobre todo a la hora de construir interfaces de usuario complejas, en las que pueda haber Componentes que solapen a otros Componentes o a parte de ellos.

viernes, 13 de diciembre de 2019

Herencia

Podemos utilizar una Clase para pasar todos sus atributos y métodos a otra. La primera se llama superclase o padre y la segunda hija. En Java no existe herencia múltiple, sino de una sola Clase a otra, y así sucesivamente.
Por ejemplo, tenemos una Clase Persona, con los atributos:
Fecha fechaNacimiento;
String poblacionNacimiento;
String nombre;
String apellidos;
String domicilio;
String telefono;

Y unos métodos setters y getters que modifican y visualizan los atributos anteriores.

Si queremos crear la Clase Alumno hija de la anterior bien completada se entiende, tendrá todos los atributos y métodos de la Clase Persona, pero le podremos añadir los que queramos, para ello necesitamos añadir una palabra a la Clase hija: extends, en la cabecera de la definición de la Clase hija:
public class Alumno extends Persona {   };

y un método: super( ), con los parámetros materiales que tenga el método constructor de la superclase, pues hace sus veces. Este método se debe incluir en el método constructor de la Clase hija y además en primer lugar. La Clase Alumno,  heredará los atributos y métodos de la Clase Persona o padre o superclase, y la completamos con los atributos y métodos que necesitemos. Tendremos también, seguramente, que completar el constructor.
De la Clase Persona podríamos extender otras Clases como Profesor, y de ésta otras, según nos interese. Pero toda Clase  extendida heredará todos los parámetros y métodos de su Clase madre, aunque podamos modificarlos, y hacer, con el casting, utilizar uno u otros de las Clases superiores.

jueves, 12 de diciembre de 2019

Secuencias enlazadas. La clase Nodo

Un nodo es una estructura de Java que asocia un dato de una Clase con el enlace o referencia al siguiente nodo.

public class NodoCF{//Dos datos tipo String, una referencia al siguiente NodoCF y un contador, //variable entera de Clase
    String nombre;//Hemos elegido los miembros elegidos por el CF del Psoe, por ser públicos.
    String ciudad;
    NodoCF siguiente;
    static int k;

    public NodoCF(String n,String c){//El primer constructor solo introduce el nombre y la ciudad del //primero de la lista
      this.nombre = n;
      this.ciudad = c;
      this.siguiente = null;//como es el primer nodo construido no hay referencia a otro.
    }

     public NodoCF(String n, String c, NodoCF s){//El segundo constructor permite introducir el //nombre y la ciudad de los siguientes de la lista
      this.nombre = n;
      this.ciudad = c;
      this.siguiente = s;//como ya hay un nodo construido hay referencia a él, 
      //de modo consecutivo se utiliza repetitivamente este constructor.
    }
    
    public String toString(){//Este método permite listarlos, pero en el orden inverso al que se han //introducido
    NodoCF aux = this.siguiente; String st = null; k=1;  
    while(aux!=null){
        st= k+".- "+aux.nombre+" ("+aux.ciudad+")";
        System.out.println(st);
        aux = aux.siguiente;k++;
    } 
    return st;
    }
}


public class ProgramCF{//Programa que construye secuencialmente la lista y los escribe// en pantalla.
   
    public static void main(String[] arg){
       NodoCF sec = new NodoCF("Juan Cornejo López ","Andalucía");
        sec = new NodoCF("Joan Jesús Ros Piles ","Valencia",sec);
        sec = new NodoCF("Sergio Gutiérrez Prieto ","CLM",sec);
        sec = new NodoCF("Marisol Mateos Nogales ","Extremadura",sec);
        sec = new NodoCF("Miguel Ángel Morales Quicios ","Euskadi" ,sec);
        sec = new NodoCF("Ana Sánchez Hernandez ","CyL",sec);
        sec = new NodoCF("Gonzalo Caballero Miguez ","Galicia",sec);
        sec = new NodoCF("Gimena Llamedo González ","Asturias",sec);
        sec = new NodoCF("Carmen Barahona Prol ","Madrid",sec);
        sec = new NodoCF("Mª José Camps Orfila ","Baleares",sec);
        sec = new NodoCF("Sabrina Moh Abdelkader ","Melilla",sec);
        sec = new NodoCF(" ","",sec);
        sec.toString();      
    }
}

En pantalla: (Al revés)

1.- Sabrina Moh Abdelkader  (Melilla)
2.- Mª José Camps Orfila  (Baleares)
3.- Carmen Barahona Prol  (Madrid)
4.- Gimena Llamedo González  (Asturias)
5.- Gonzalo Caballero Miguez  (Galicia)
6.- Ana Sánchez Hernandez  (CyL)
7.- Miguel Ángel Morales Quicios  (Euskadi)
8.- Marisol Mateos Nogales  (Extremadura)
9.- Sergio Gutiérrez Prieto  (CLM)
10.- Joan Jesús Ros Piles  (Valencia)
11.- Juan Cornejo López  (Andalucía)

Esta estructura de filas secuenciales permite manejar infinidad de datos.

miércoles, 9 de octubre de 2019

Arrays lineales o de una dimensión

Podemos imaginar una calle mas o menos larga que tenga en uno de los lados aparcamientos señalizados y numerados secuencialmente del 0 a n-1. Los aparcamientos pueden estar en serie o en batería, para nosotros no importa. Esto es un array unidimensional de n componentes (aparcamiento).
En este array solo pueden aparcar coches en principio; se podría hacer un casting para que aparcaran furgonetas, ... ESTE ES EL PRINCIPIO FUNDAMENTAL DEL ARRAY: SOLO PUEDEN CONTENER DATOS DEL MISMO TIPO. No podemos poner bicicletas, ni contenedores, ni paradas de autobús.
De los arrays lineales podemos siempre saber el número de componentes que tiene con la variable numérica entera "length". Así, si el array antes descrito le llamamos parking, podemos saber el número de plazas de coche -solamente de coches, salvo casting- así: parking.length  y nos dá su numero de componentes o la capacidad del parking total. El array es un objeto en Java: tiene constructor, y a la vez en cada componente podemos poner un objeto, en este caso coche, pero sin ponerlo: ponemos solo la referencia o dirección de memoria en la que se encuentra el coche en el heap de memoria del ordenador: es decir, en el parking no habrá un solo coche, en cada aparcamiento tendremos un "papelito" donde está escrito donde se encuentra el objeto coche en el heap de la memoria.

Cuando en un array guardamos datos del mismo tipo, pero primitivos (int, boolean, doubles, char, ...), éstos sí se guardan directamente en las componentes del array. Los String son objetos y se guardan sus referencias, como los coches por ejemplo.

La gran ventaja de los arrays es que podemos acceder directamente a sus componentes.

Declaración de un array lineal: Se dechara poniendo el tipo de Dato u objeto, dos corchetes: [], y el nombre del array que le demos, puede ser cualquiera pero guardando las especificaciones del lenguaje java para los nombres, y que sean lo mas descriptivo posible del objeto o dato primitivo:

int [] numCoches;
double [] kilosPesoCoches;
String [] marcaCoches;
Coche [] coche;

Y se definen y crean como cualquier objeto, un poco especial, con el new:

int [] numCoches = new int[n];
double [] kilosPesoCoches = new double[n];
String [] marcaCoches = new String[n]
Coche [] coche = new Coche[n];

Se supone que nos estamos moviendo en el mismo parking con n aparcamientos.