I made this widget at MyFlashFetish.com.


   
 
  CUESTIONARIO DE LA UNIDAD 5
UNIDAD 5.

IMPLEMENTACION DE LA CLASE.

1.- DEFINA QUE ES UNA CLASE:

Las clases son la base de la Programación Orientada a Objetos. Una clase es una plantillaque define la forma de un objeto; en ella se agrupan datos y métodos que operarán sobre esos datos. Enjava, una clase se define con la palabra reservada class. En la figura se muestra la forma general para ladefinición de una clase:

Por convención, se declaran primero las variables (atributos) miembro de la clase y luego lasdeclaraciones e implementaciones de métodos.

Al diseñar una clase es conveniente tomar en cuenta lo siguiente:
· En Java no existen variables ni métodos globales. Todas las variables y métodos debenpertenecer a una clase.
· Cuando una clase extiende a otra hereda todas sus atributos y métodos.
· En Java no existe la herencia múltiple.
· Object es la base de toda la jerarquía de clases de Java. Si al definir una clase no se especificala clase que extiende, por default deriva de Object.


2.-EXPLIQUE AMPLIAMENTE QUE ES UN MODIFICADOR DE ACCESO, PARA QUE SE UTILIZA Y QUE TIPOS EXISTEN:
Los modificadores de acceso a clase son opcionales, se anteponen a la palabra reservada class, estosson public, abstract y final.

public: la clase puede ser utilizada por objetos que estén fuera del paquete actual. Por omisión, unaclase sólo puede ser utilizada por otras clases dentro del mismo paquete en el que están declaradas.

abstract:
Se usa para indicar que una clase es abstracta, esto significa que la clase puede contener métodos sin implementación (abstractos). Una clase abstracta está diseñada para ser una superclase y no pueden crear objetos de ella.

final:
cuando una clase tiene el modificador final es una clase que no puede tener subclases.


3.-DE LOS DIFERENTES TIPOS DE MODIFICADORES DE ACCESO ILUSTRE 5 EJEMPLOS DE APLICACION DE MODIFICADORES DE ACCESO DE MANERA INDEPENDIENTE:

Modificadores de acceso

Los modificadores de acceso sirven para restringir el acceso a los campos o a los métodos de una clase.

Los principales modificadores de acceso son:

  • private
  • protected
  • public

El modificador private permite que el campo o método sólo pueda ser accedido dentro de la clase donde fue declarado.

El modificador protected permite que el campo o método sólo pueda ser accedido dentro de la clase donde fue declarado y en todas las clases derivadas de ella.

El modificador public permite que el campo o método pueda ser accedido desde cualquier clase.

4.-EXPLIQUE AMPLIAMENTE EN QUE CONSISTE EL CONCEPTO DE "ENCAPSULAMIENTO" DE LA CLASE:

Describe la vinculacion de unas operaciones y estado a un objeto particular . La encapsulacion esta intimamente vinculada con la ocultacion de la informacion  , definiendo que partes de un objeto son visibles y que partes estan ocultas

5.-ILUSTRE 5 EJEMPLOS DIFERENTES DONDE USTED UTILICE EL ENCAPSULAMIENTO DE LA CLASE, EXPLICANDO CUAL ES LA CLASE Y CUALES SON SUS ELEMENTOS DE LA CLASE:

Encapsulamiento de los atributos de una clase

Antes de nada, debe quedar claro que el encapsulamiento, igual que cualquier buen hábito de programación (como no poner goto, comentar, etc) es útil para código que más adelante se puede querer reutilizar o modificar, por otras personas o por uno mismo. Si yo hago un programa de marcianos y nunca jamas pienso volver a tocarlo, da igual que lo haga con gotos y sin comentar mientras me entere yo mismo mientras lo estoy haciendo y funcione. Pagaré este "pecado" si dentro de dos meses se me ocurre mejorarlo o quiero reaprovechar algo de su código para otro programa.

 

Cualquier curso de orientación a objetos nos dice que es mejor poner los atributos de una clase protegidos o privados (nunca públicos) y acceder a ellos a través de métodos públicos que pongamos en la clase. Veamos el motivo. Supongamos, por ejemplo, que nos piden un programa que permita llevar una lista de gente con sus fechas de nacimiento. Entre otras cosas, decidimos hacernos nuestra clase Fecha con varios métodos maravillosos de la siguiente manera. 

class Fecha
{
   public:
      int anho; // El anho con cuatro cifras, ej. 2004
      int mes;  // El mes, de 1 a 12
      int dia;    // El dia, de 1 a 31
      void metodoMaravilloso1();
      void metodoMaravilloso2();
};

·             Ya hemos hecho la clase. Ahora hacemos el resto del código y en unos varios miles de líneas de código usamos directamente cosas como esta. 

Fecha unaFecha;
unaFecha.anho = 2004;
unaFecha.mes = 1;
unaFecha.dia = 25;

  Finalmente acabamos nuestro programa y todo funciona de maravilla. Unos días después nos dicen que el programa va a guardar tropecientas mil personas y que ocupan mucho los ficheros, que a ver si podemos hacer algo para remediarlo. ¡Vaya!, almacenamos una fecha con tres enteros. Si usamos el formato de la mayoría de los ordenadores, en el que la fecha es el número de segundos transcurridos desde el 1 de Enero de 1970 (lo que nos devuelve la función time()), basta con un entero.

Total, que manos a la obra, cambiamos nuestra clase para que tenga lo siguiente: 

class Fecha
{
   public:
      /* Comentado por ineficiente
      int anho; 
      int mes; 
      int dia;   */

      long numeroSegundos;

      void metodoMaravilloso1();
      void metodoMaravilloso2();
};

Ya está hecho lo fácil. Ahora sólo hay que ir por las tropecientas mil líneas de código cambiando nuestras asignaciones y lecturas a los tres enteros anteriores por el nuevo long.

·             Hubiera sido mucho mejor si hubieramos hecho estos tres enteros protegidos y unos métodos para acceder a ellos. Algo como esto 

class Fecha
{
   public:
      void tomaFecha (int anho, int mes, int dia);
      int dameAnho ();
      int dameMes ();
      int dameDia ();
      void metodoMaravilloso1();
      void metodoMaravilloso2();
   protected:
      int anho; // El anho con cuatro cifras, ej. 2004
      int mes;  // El mes, de 1 a 12
      int dia;    // El dia, de 1 a 31
};

Si ahora tenemos que hacer el mismo cambio, basta con cambiar los atributos protegidos. Los métodos tomaXXX() y dameXXX() se mantienen en cuanto a parámetros y valor devuelto, pero se modifica su código interno para que conviertan el año,mes y dia en un long de segundos y al revés. El resto del código no hay que tocarlo en absoluto.

·             Es incluso mejor hacer los atributos privados que protegidos. Haciéndolos protegidos, las clases hijas (las que heredan de Fecha) pueden acceder directamente a estos atributos. Cuando hagamos el cambio por un long, debemos cambiar también el código de las clases hijas. Si los atributos son privados y obligamos a las clases hijas a acceder a ellos a través de métodos, tampoco tendremos que cambiar el código de estas clases hijas.

El acceso a través de métodos es menos eficiente que hacerlo directamente, así que aunque siguiendo el principio de ocultación es mejor hacer atributos privados, por eficiencia en algunos casos quizás sea mejor hacerlos protegidos (o incluso públicos) a riesgo de tener que cambiar más líneas de código en caso de cambio.

 

CONSEJO:
Siempre que sea posible hacer los atributos de una
clase privados.

         Importancia de la encapsulación en C++

Con lo contado hasta ahora evitamos tener que cambiar código en caso de cambiar parámetros.

 

En el caso concreto de C++ hay un pequeño problema adicional. Es bastante normal hacer que las clases se definan por medio de dos ficheros. En el caso de la clase Fecha tendríamos un Fecha.h con la definición de la clase y un Fecha.cc (o .cpp) con el código de los métodos de la clase. Cuando queremos usar la clase Fecha, solemos hacer nuestro #include <Fecha.h>.

Cualquier proceso de compilado eficiente (como la utilidad make de linux y supongo que el Visual C++) es lo suficientemente listo como para recompilar sólo aquellos ficheros que es necesario recompilar. Es decir, si ya tenemos nuestro proyecto compilado y tocamos un fichero, el compilador sólo compilará ese fichero y todos los que dependen de él. Esta características es muy importante en proyectos grandes (con muchos ficheros y muchas líneas de código), para ahorrar tiempo de compilado cada vez que hacemos una modificación (He trabajado en proyectos que tardaban en compilar desde cero alrededor de 4 horas).

 

¿Cual es el problema?. El problema es que si decidimos, por ejemplo, cambiar nuevamente el atributo privado de la clase Fecha por otra cosa, necesitamos tocar el fichero Fecha.h. Esto hará que se recompilen todos los ficheros que hagan #include <Fecha.h> y todos los ficheros que hagan #include de algun fichero que a su vez haga #include de Fecha.h y así sucesivamente.

 

La solución es evidente, colocar lo menos posible en el fichero Fecha.h, en concreto los #define y variables globales que no sea necesario ver desde otras clases.

 

Por ejemplo, nuestra clase Fecha podía tener unos #define para indicar cual es el número mínimo y máximo de mes. Es mejor colocar estos #define en Fecha.cc en vez de en Fecha.h, salvo que alguien tenga que verlos. 

// Esto mejor en el .cc que en el .h
#define MES_MINIMO 1
#define MES_MAXIMO 12

·

CONSEJO:
Siempre que sea posible, poner los #define, definición de tipos,
constantes globales, etc, dentro del fichero .cc

Encapsulamiento a través de interfaces

Nos queda una cosa. ¿Por qué tenemos que recompilar muchas cosas si cambiamos un atributo privado de la clase?. Lo ideal sería poder cambiar las cosas internas de la clase sin que haya que recompilar nada más, a fin de cuentas, el atributo es privado y nadie lo utiliza directamente.

 

Es bastante habitual en programación orientada a objetos el uso de interfaces para hacer que las clases no dependan entre sí. En el caso de C++ el uso de interfaces es útil además para evitar recompilados innecesarios.

 

Una interface no es más que una clase en la que se definen los métodos públicos necesarios, pero no se implementan. Luego la clase concreta que queramos hacer hereda de esa interface e implementa sus métodos.

 

En nuestro caso, podemos hacer una clase InterfaceFecha, con los métodos públicos virtuales puros (sin código). Luego la clase Fecha hereda de InterfaceFecha e implementa esos métodos.

 

En el fichero InterfaceFecha.h tendríamos
 

class InterfaceFecha
{
   public:
      virtual void tomaFecha (int anho, int mes, int dia) = 0;
      virtual int dameAnho () = 0;
      virtual int dameMes () = 0;
      virtual int dameDia () = 0;
      virtual void metodoMaravilloso1() = 0;
      virtual void metodoMaravilloso2() = 0;
};

De momento, ni siquiera existiría un InterfaceFecha.ccLa clase Fecha sigue igual, pero hereda de InterfaceFecha.

 

#include <InterfaceFecha.h>

class Fecha : public InterfaceFecha
{
   public:
      void tomaFecha (int anho, int mes, int dia);
      int dameAnho ();
      int dameMes ();
      int dameDia ();
      void metodoMaravilloso1();
      void metodoMaravilloso2();
   protected:
      int anho; // El anho con cuatro cifras, ej. 2004
      int mes;  // El mes, de 1 a 12
      int dia;    // El dia, de 1 a 31
};

Ahora, todo el que necesite una Fecha, tiene que tener un puntero a InterfaceFecha en vez de a Fecha. Alguien instanciará Fecha y lo guardará en ese puntero. Es decir, podríamos hacer algo como esto

 

#include <Fecha.h>
#include <InterfaceFecha.>
...
InterfaceFecha *unaFecha = NULL;
...
unaFecha = new Fecha();
unaFecha->tomaFecha (2004, 1, 27);
...
delete unaFecha;
unaFecha = NULL;

 

 

Si nos fijamos un poco, todavía no hemos arreglado nada, salvo complicar el asunto. El que haga este código necesita hacer ahora #include tanto de InterfaceFecha.h como de Fecha.h. Si tocamos algo en Fecha.h, este código se recompilará.

Este código necesita #include <Fecha.h> para poder hacer el new de Fecha. Hay que buscar la forma de evitar ese new. Suele ser también bastante habitual hacer una clase (o utilizar la misma Interface si el lenguaje lo permite, como es el caso de C++) para poner un método estático que haga el new y nos lo devuelva.

 

En el caso de Java, al poner este método, ya no tendríamos una interface, sino una clase. Hacer que Fecha herede de InterfaceFecha nos limita a no heredar de otra cosa (Java no admite herencia múltiple). Si esto es admisible, podemos hacerlo así. Si necesitamos que Fecha herede de otra clase, en vez de poner el método estático en la interface, debemos hacer una tercera clase aparte GeneradorFecha con este método estático.

 

En nuestro ejemplo de C++, la clase InterfaceFecha quedaría. 

class InterfaceFecha
{
   public:

      static InterfaceFecha *dameNuevaFecha();

      virtual void tomaFecha (int anho, int mes, int dia) = 0;
      virtual int dameAnho () = 0;
      virtual int dameMes () = 0;
      virtual int dameDia () = 0;
      virtual void metodoMaravilloso1() = 0;
      virtual void metodoMaravilloso2() = 0;
};Ahora sí necesitamos un InterfaceFecha.cc. Dentro de él tendriamos 

#include <InterfaceFecha.h>
#include <Fecha.h>

InterfaceFecha *InterfaceFecha::dameNuevaFecha()
{
   return new Fecha();
}

El código que antes utilizaba el puntero a InterfaceFecha quedaría ahora 

#include <InterfaceFecha.>
...
InterfaceFecha *unaFecha = NULL;
...
unaFecha = InterfaceFecha::dameNuevaFecha();
unaFecha->tomaFecha (2004, 1, 27);
...
delete unaFecha;
unaFecha = NULL;

Como vemos, sólo es necesario el #include de InterfaceFecha.h y este no incluye a Fecha.h (lo hace InterfaceFecha.cc, no el .h). Hemos hecho que este código no vea en absoluto a Fecha.h. Ahora podemos tocar sin ningún miramiento el fichero Fecha.h, que este código no necesita ser recompilado.

 

Una ventaja adicional es que se puede cambiar la clase Fecha por otra clase Fecha2 en tiempo de ejecución. Bastaría con poner un atributo estático en InterfaceFecha para indicar qué clase Fecha queremos y hacer que el método dameNuevaFecha() instancie y devuelve una u otra en función de ese atributo. 

CONSEJO:
Utilizar interfaces para aquellas clases que preveamos que
pueden cambiar durante el desarrollo del proyecto o
que creamos que podemos cambiar más adelante por otra.

Este mecanismo de obtener una instancia de una clase a través de un método estático y de una interface, para no depender de la clase concreta, creo que dentro del mundo de los patrones de diseño es el patrón Factoria.

6.-EXPLIQUE AMPLIAMENTE COMO SE COMUNICAN LOS ELEMENTOS QUE FORMAN PARTE DE UN PROGRAMA ORIENTADO A OBJETOS:

7.-DEFINE ELCONCEPTO DE METODO Y EXPLIQUE AMPLIAMENTE PARA QUE SIRVE Y COMO SE UTILIZA :

Los métodos son funciones que pueden ser llamadas dentro de la clase o por otras clases. La implementación de un método consta de dos partes, una declaración y un cuerpo. La declaración en Java de un método se puede expresar esquemáticamente como:

    tipoRetorno nombreMetodo( [lista_de_argumentos] ) {

        cuerpoMetodo

        }

En C++, el método puede declararse dentro de la definición de la clase, aunque también puede colocarse la definición completa del método fuera de la clase, convirtiéndose en una función inline. En Java, la definición completa del método debe estar dentro de la definición de la clase y no se permite la posibilidad de métodos inline, por lo tanto, Java no proporciona al programador distinciones entre métodos normales y métodos inline.

Los métodos pueden tener numerosos atributos a la hora de declararlos, incluyendo el control de acceso, si es estático o no estático, etc. La sintaxis utilizada para hacer que un método sea estático y su interpretación, es semejante en Java y en C++. Sin embargo, la sintaxis utilizada para establecer el control de acceso y su interpretación, es muy diferente en Java y en C++.

La lista de argumentos es opcional, tanto en Java como en C++, y en los dos casos puede limitarse a su mínima expresión consistente en dos paréntesis, sin parámetro alguno en su interior. Opcionalmente, C++ permite utilizar la palabra void para indicar que la lista de argumentos está vacía, en Java no se usa. Los parámetros, o argumentos, se utilizan para pasar información al cuerpo del método.

La sintaxis de la declaración completa de un método es la que se muestra a continuación con los items opcionales en itálica y los items requeridos en negrilla:

especificadorAcceso static abstract

    final native synchronized tipoRetorno nombreMetodo( lista_de_argumentos )

    throws listaEscepciones

especificadorAcceso, determina si otros objetos pueden acceder al método y cómo pueden hacerlo. Está soportado en Java y en C++, pero la sintaxis e interpretación es considerablemente diferente.

static, indica que los métodos pueden ser accedidos sin necesidad de instanciar un objeto del tipo que determina la clase. C++ y Java son similares en el soporte de esta característica.

abstract, indica que el método no está definido en la clase, sino que se encuentra declarado ahí para ser definido en una subclase (sobreescrito). C++ también soporta esta capacidad con una sintaxis diferente a Java, pero con similar interpretación.

final, evita que un método pueda ser sobreescrito.

native, son métodos escritos es otro lenguaje. Java soporta actualmente C y C++.

synchronized, se usa en el soporte de multithreading, que se verá también en este Tutorial.

lista_de_argumentos, es la lista opcional de parámentros que se pueden pasar al método

throws listaExcepciones, indica las excepciones que puede generar y manipular el método. También se verán en este Tutorial a fondo las excepciones en Java.

8.-TOMANDO COMO EJEMPLOS DE PROGRAMACION 5 PROGRAMAS DIFERENTES ILUSTRE COMO SE

En Java es imprescindible que a la hora de la declaración de un método, se indique el tipo de dato que ha de devolver. Si no devuelve ningún valor, se indicará el tipo
void como retorno.

Los métodos y funciones en C++ pueden devolver una variable u objeto, bien sea por valor (se devuelve una copia), por puntero o por referencia. Java no soporta punteros, así que no puede devolver nada por puntero. Todos los tipos primitivos en Java se devuelven por valor y todos los objetos se devuelven por referencia. El retorno de la referencia a un objeto en Java es similar a devolver un puntero a un objeto situado en memoria dinámica en C++, excepto que la sintaxis es mucho más simple en Java, en donde el item que se devuelve es la dirección de la posición en memoria dinámica donde se encuentra almacenado el objeto.

Para devolver un valor se utiliza la palabra clave return. La palabra clave return va seguida de una expresión que será evaluada para saber el valor de retorno. Esta expresión puede ser compleja o puede ser simplemente el nombre de un objeto, una variable de tipo primitivo o una constante.

El ejemplo java506.java ilustra el retorno por valor y por referencia.

    // Un objeto de esta clase sera devuelto por referencia
    class miClase {
        int varInstancia = 10;
        }

Si un programa Java devuelve una referencia a un objeto y esa referencia no es asignada a ninguna variable, o utilizada en una expresión, el objeto se marca inmediatamente para que el reciclador de memoria en su siguiente ejecución devuelve la memoria ocupada por el objeto al sistema, asumiendo que la dirección no se encuentra ya almacenada en ninguna otra variable. En C++, si un programa devuelve un puntero a un objeto situado en memoria dinámica y el valor de ese puntero no se asigna a una variable, la posibilidad de devolver la memoria al sistema se pierde y se producirá un memory leak, asumiendo que la dirección no está ya disponible para almacenar ninguna otra variable.

Tanto en Java como en C++ el tipo del valor de retorno debe coincidir con el tipo de retorno que se ha indicado en la declaración del método; aunque en Java, el tipo actual de retorno puede ser una subclase del tipo que se ha indicado en la declaración del método, lo cual no se permite en C++. En Java esto es posible porque todas las clases heredan desde un objeto raíz común a todos ellos: Object.

En general, se permite almacenar una referencia a un objeto en una variable de referencia que sea una superclase de ese objeto. También se puede utilizar un interfaz como tipo de retorno, en cuyo caso, el objeto retornado debe implementar dicho interfaz.

Nombre del Método

El nombre del método puede ser cualquier identificador legal en Java. Java soporta el concepto de sobrecarga de métodos, es decir, permite que dos métodos compartan el mismo nombre pero con diferente lista de argumentos, de forma que el compilador pueda diferenciar claramente cuando se invoca a uno o a otro, en función de los parámetros que se utilicen en la llamada al método.

El siguiente fragmento de código muestra una clase Java con cuatro métodos sobrecargados, el último no es legal porque tiene el mismo nombre y lista de argumentos que otro previamente declarado:

    class MiClase {
        . . .
        void miMetodo( int x,int y ) { . . . }
        void miMetodo( int x ) { . . . }
        void miMetodo( int x,float y ) { . . . }
        // void miMetodo( int a,float b ) { . . . } // no válido
       }

Todo lenguaje de programación orientado a objetos debe soportar las características de encapsulación, herencia y polimorfismo. La sobrecarga de métodos es considerada por algunos autores como polimorfismo en tiempo de compilación.

En C++, dos versiones sobrecargadas de una misma función pueden devolver tipos diferentes. En Java, los métodos sobrecargados siempre deben devolver el mismo tipo.

Métodos de Instancia

Cuando se incluye un método en una definición de una clase Java sin utilizar la palabra clave static, estamos generando un método de instancia. Aunque cada objeto de la clase no contiene su propia copia de un método de instancia (no existen múltiples copias del método en memoria), el resultado final es como si fuese así, como si cada objeto dispusiese de su propia copia del método.

Cuando se invoca un método de instancia a través de un objeto determinado, si este método referencia a variables de instancia de la clase, en realidad se están referenciando variables de instancia específicas del objeto específico que se está invocando.

La llamada a los métodos de instancia en Java se realiza utilizando el nombre del objeto, el operador punto y el nombre del método.

    miObjeto.miMetodoDeInstancia();

En C++, se puede acceder de este mismo modo o utilizando una variable puntero que apunte al objeto

    miPunteroAlObjeto->miMetodoDeInstancia();

Los métodos de instancia tienen acceso tanto a las variables de instancia como a las variables de clase, tanto en Java como en C++.

Métodos Estáticos

Cuando una función es incluida en una definición de clase C++, o un método e incluso en una definición de una clase Java, y se utiliza la palabra static, se obtiene un método estático o método de clase.

Lo más significativo de los métodos de clase es que pueden ser invocados sin necesidad de que haya que instanciar ningún objeto de la clase. En Java se puede invocar un método de clase utilizando el nombre de la clase, el operador punto y el nombre del método.

    MiClase.miMetodoDeClase();

En C++, hay que utilizar el operador de resolución de ámbito para poder invocar a un método de clase:

    MiClase::miMetodoDeClase();

En Java, los métodos de clase operan solamente como variables de clase; no tienen acceso a variables de instancia de la clase, a no ser que se cree un nuevo objeto y se acceda a las variables de instancia a través de ese objeto.

Si se observa el siguiente trozo de código de ejemplo:

    class Documento extends Pagina {
        static int version = 10;
        int numero_de_capitulos;
        static void annade_un_capitulo() {
            numero_de_capitulos++; // esto no funciona
            }
        static void modifica_version( int i ) {
            version++;             // esto si funciona
            }
        }

la modificación de la variable numero_de_capitulos no funciona porque se está violando una de las reglas de acceso al intentar acceder desde un método estático a una variable no estática.

Todas las clases que se derivan, cuando se declaran estáticas, comparten la misma página de variables; es decir, todos los objetos que se generen comparten la misma zona de memoria. Los métodos estáticos se usan para acceder solamente a variables estáticas.

    class UnaClase {
        int var;
        UnaClase() {
            var = 5;
            }
        unMetodo() {
            var += 5;
            }
        }

En el código anterior, si se llama al método unMetodo() a través de un puntero a función, no se podría acceder a var, porque al utilizar un puntero a función no se pasa implícitamente el puntero al propio objeto (this). Sin embargo, sí se podría acceder a var si fuese estática, porque siempre estaría en la misma posición de memoria para todos los objetos que se creasen de la clase UnaClase.

Paso de parámetros

En C++, se puede declarar un método en una clase y definirlo luego dentro de la clase (bajo ciertas condiciones) o definirlo fuera de la clase. A la hora de declararlo, es necesario indicar el tipo de argumentos que necesita, pero no se requiere indicar sus nombres (aunque pueda hacerse). A la hora de definir el método sí tiene que indicarse el nombre de los argumentos que necesita el método.

En Java, todos los métodos deben estar declarados y definidos dentro de la clase, y hay que indicar el tipo y nombre de los argumentos o parámetros que acepta. Los argumentos son como variables locales declaradas en el cuerpo del método que están inicializadas al valor que se pasa como parámetro en la invocación del método.

En Java, todos los argumentos de tipos primitivos deben pasarse por valor, mientras que los objetos deben pasarse por referencia. Cuando se pasa un objeto por referencia, se está pasando la dirección de memoria en la que se encuentra almacenado el objeto.

Si se modifica una variable que haya sido pasada por valor, no se modificará la variable original que se haya utilizado para invocar al método, mientras que si se modifica una variable pasada por referencia, la variable original del método de llamada se verá afectada de los cambios que se produzcan en el método al que se le ha pasado como argumento.

El ejemplo java515.java se ilustra el paso de parámetros de tipo primitivo y también el paso de objetos, por valor y por referencia, respectivamente.

// Esta clase se usa para instanciar un objeto referencia
class MiClase {
    int varInstancia = 100;
    }
    
// Clase principal
class java515 {
    
    // Función para ilustrar el paso de parámetros
    void pasoVariables( int varPrim,MiClase varRef ) {
        System.out.println( "--> Entrada en la funcion pasoVariables" );
        System.out.println( "Valor de la variable primitiva: "+varPrim );
        System.out.println( "Valor contenido en el objeto: "+
            varRef.varInstancia );
    
        System.out.println( "-> Modificamos los valores" );
        varRef.varInstancia = 101;
        varPrim = 201;
    
        System.out.println( "--> Todavia en la funcion pasoVariables" );
        System.out.println( "Valor de la variable primitiva: "+varPrim );
        System.out.println( "Valor contenido en el objeto: "+
            varRef.varInstancia );
        }
    
    public static void main( String args[] ) {
        // Instanciamos un objeto para acceder a sus métodos
        java515 aObj = new java515();
    
        // Instanciamos un objeto normal
        MiClase obj = new MiClase();
        // Instanciamos una variable de tipo primitivo
        int varPrim = 200;
    
        System.out.println( "> Estamos en main()" );
        System.out.println( "Valor de la variable primitiva: "+varPrim );
        System.out.println( "Valor contenido en el objeto: "+
            obj.varInstancia );
        // Llamamos al método del objeto
        aObj.pasoVariables( varPrim,obj );
    
        System.out.println( "> Volvemos a main()" );
        System.out.println( "Valor de la variable primitiva, todavia : "+
            varPrim );
        System.out.println( "Valor contenido ahora en el objeto: "+
            obj.varInstancia );
        }
    }

En C++, se puede pasar como parámetro un puntero que apunte a una función dentro de otra función, y utilizar este puntero en la segunda función para llamar a la primera. Esta capacidad no está directamente soportada en Java. Sin embargo, en algunos casos, se puede conseguir casi lo mismo encapsulando la primero función como un método de instancia de un objeto y luego pasar el objeto a otro método, donde el primer método se puede ejecutar a través del objeto.

Tanto en Java como en C++, los métodos tienen acceso directo a las variables miembro de la clase. El nombre de un argumento puede tener el mismo nombre que una variable miembro de la clase. En este caso, la variable local que resulta del argumento del método, oculta a la variable miembro de la clase.

Cuando se instancia un método se pasa siempre una referencia al propio objeto que ha llamado al método, es la referencia this.

Definición de métodos de una clase

Para definir los métodos se emplea la siguiente sintaxis:

[modifVisibilidad] [modifFunción] tipo nombreFunción (listaParámetros) [throws listaExcepciones]

{

}

Para modifVisibilidad se aplica las mismas normas que para atributos:

public: indica que es un método accesible a través de una instancia del objeto.

private: indica que a través de una instancia no es accesible el método. Al heredar el método se convierte en inaccesible.

protected: indica que a través de una instancia no es accesible el método. Al heredar si se puede usar desde la clase derivada.

Sin especificar: indica visibilidad de paquete, se puede acceder a través de una instancia, pero sólo de clases que se encuentren en el mismo paquete.

nombreFunc debe de ser un identificador válido en el lenguaje.

tipo es el tipo del valor devuelto por la función, pudiendo ser:

Un tipo básico.

Un objeto de una clase o interfaz. En este tipo de objetos se incluyen las matrices o vectores.

void, en el caso de no devolver ningún valor.

Métodos

El comcepto de método consiste es una forma de encapsular un conjunto de instrucciones dentro de una declaración específica (llamada generalmente SUBPROGRAMA), permitiendo la descomposición funcional y la diferenciación de tareas.

La declaración de un método está formada por una cabecera y un cuerpo.

Estructuración en Java

La codificación de un método consiste en una cabecera para su identificación y de un cuerpo que contiene las sentencias que éste ejecuta. La cabecera se compone de un nombre (identificador del método), el tipo del resultado(tipos primitivos o clases) y una lista de parámetros, que puede contener cero o más variables.

La lista de parámetros consiste en cero o más parámetros formales (variables), cada uno de ellos con un tipo.
En caso que el método tenga más de un parámetro, estos deben ir separados con una coma.

Llamada a un método

Los métodos pueden ser invocados o llamados de cualquier método de la clase, incluido él mismo.
Además, cuando se invoca, hay que pasar un valor a cada paramétro, a través de una variable o un valor constante. En Java, la acción de pasar valores a parámetros de tipo primitivo (int, double, boolean, char..) se denomina paso de parámetros por valor
En éste caso, los argumentos que se pasan, no pueden ser modificados por la función.

En caso que el parámetro sea de tipo Clase o arreglo, lo que se está haciendo es un paso de parámetros por referencia, y en este caso, los parámetros si pueden ser modificados por el método

Cuerpo

El código que realmente implementa el método,llamado cuerpo del método ,es formalmente un bloque de instrucciones.

Ejemplo

/* 1) */    int sumar(int a , int b)
/* 2) */    {
/* 3) */        return a + b;
/* 4) */    }

1) cabecera del método : int sumar(int a,int b)

tipo del resultado : int
nombre del método : sumar
lista de parámetros : int a,int b

2) comienzo del bloque o cuerpo del método

3) Instrucción : se retorna la suma de a y b

4) fin del bloque

Si se coloca las palabras public static antes del método se logra un comportamiento de tipo global.

import java.io.*;
class suma
{
    public static void main(String arg[ ]) throws IOException
    {
        int x,y;
 
        BufferedReader in = new BufferedReader(new 
            InputStreamReader(System.in));
 
        System.out.print("Ingrese un numero : ");
        x = Integer.parseInt(in.readLine( ));
    
        System.out.print("Ingrese un numero : ");
        y = Integer.parseInt(in.readLine( ));
    
        int s = suma(x,y);
        
        System.out.println("La suma es : " + s);
    }    
    
    public static int suma(int a,int b)
    {
        return a + b;    
    }
    
}

Ejemplo de llamada a un método que determina si un número es par o impar

class metodo1

{

    public static void main(String arg[ ])

    {

        int a = 5;

       

        if ( par(a) == true)

        {

            System.out.println(a + " es par ");   

        }

        else

        {

            System.out.println(a + " es impar");   

        }

    }   

   

    public static boolean par(int num)

    {

        boolean p = false;

        if (num % 2 == 0)

        {

            p = true;

        }   

       

        return p;

    }

}

Ejemplo

Tomando los algoritmos para invertir un numero especificados en la sección de Manipulación numérica implementar un programa en java que determine los 100 primeros números palíndromes a partir de un número ingresado por teclado en adelante, llamando al método : invertir_num.

Código fuente

import java.io.*;

class palindromes

{

    public static void main(String Arg[ ]) throws IOException

    {

        int numero = 0;

        int contador = 0;

        

        BufferedReader in = new BufferedReader(new

            InputStreamReader(System.in));

 

        System.out.print("Ingrese numero : ");

        numero = Integer.parseInt(in.readLine( ));

             

        System.out.println("nLos 100 primeros palindromes a contar del " + numero);

        System.out.println("n");

    

        while (contador < 100)

        {

            if ( invertir_num(numero) == numero)

            {

                System.out.print(numero + "t");       

                contador++;

            }

           

            numero++;

        }

    }

 

 

    public static int invertir_num ( int num )

    {

        int div_entera,resto,num_inv;   

       

        num_inv = 0;

        div_entera = num;

        resto = 0;

       

        while (div_entera != 0)

        {

            resto  = div_entera % 10;

            div_entera = div_entera / 10;

            num_inv = num_inv * 10 + resto;

        }

 

        return num_inv;   

    }

}


9.-EXPLIQUE AMPLIAMENTE CUALES SON LAS REGLAS SINTACTICAS QUE SE UTILIZAN PARA COMUNICARSE A TRAVES DE LOS METODOS:

El cuerpo de los métodos

Otra vez recordaremos nuestra vieja clase Contador:

// Implementación de un contador sencillo
public class Contador {
………………..
public int incCuenta() {
cnt++;
return cnt;
}
…………………
}
 

Dentro de los métodos pueden incluirse:

  • Declaración de variables locales
  • Asignaciones a variables
  • Operaciones matemáticas
  • Llamados a otros métodos:
    • dentro de la clase
    • de instancia, de otras clases
    • de clase, de cualquier clase
  • Estructuras de control
  • Excepciones (try, catch, que veremos más adelante)

Declaración de variables locales

Las variables locales se declaran igual que los atributos de la clase:

Tipo NombreVariable [= Valor];

Ej: int suma;

float precio;

Contador laCuenta;

Sólo que aquí no se declaran private, public, etc., sino que las variables definidas dentro del método sólo son accesibles por él.

Las variables pueden inicializarse al crearse:

Ej: int suma = 0;

float precio = 12.3;

Contador laCuenta = new Contador ( );

Asignaciones a variables

Se asigna un valor a una variable mediante el signo =:

Variable = Constante | Expresión ;

Ej: suma = suma + 1;

precio = 1.05 * precio;

laCuenta.cnt = 0;

El último caso es válido si cnt es una variable pública de la clase Contador. Personalmente no creo conveniente acceder directamente a variables de otro objeto, ya que futuras modificaciones del objeto llamado o del que llama puede propender la difusión de errores… Es mejor usar métodos como getCuenta o un hipotético inicializarContador para ello. De hecho, algunos sugieren que todas las variables de una clase se declaren como private.

En el primer caso, o sea en general:

Variable = Variable Operador Expresión;

se puede escribir en forma más sencilla:

Variable Operador= Expresión;

Por ejemplo, suma = suma + 9 - cantidad;

puede escribirse: suma += 9-cantidad;

y precio = precio * 0.97;

como: precio *= 0.97;

Operaciones matemáticas

Hay varios tipos de operadores:

Unarios: + - ++ -- ~ ! (tipo) …..etc.

Se colocan antes (o en algunos casos después) de la constante o expresión.

Por ejemplo: -cnt; // cambia de signo; por ejemplo si cnt es 12 el resultado es -12; cnt no cambia.

++cnt; // equivale a cnt += 1;

cnt++; // equivale a cnt +=1; veremos la diferencia al hablar de estructuras de control

--cnt; // equivale a cnt -= 1;

cnt--; // equivale a cnt -= 1;

Binarios: + - * / % …..etc.

Van entre dos constantes o expresiones o combinación de ambas.

Por ejemplo: cnt + 2; // debuelve la suma de ambos.

promedio + ( valor / 2); // como se ve, se pueden usar paréntesis.

horas / hombres; // división.

acumulado % 3; // resto de la división entera entre ambos.

Nota: + sirve también para concatenar cadenas de caracteres; hablaremos de String y StringBuffer pronto. Cuando se mezclan Strings y valores numéricos, éstos se convierten automáticamente a cadenas:

"La frase tiene " + cant + " letras"

se convierte en: "La frase tiene 17 letras" // suponiendo que cant = 17

 Precedencia de operadores en Java

La siguiente es la precedencia de los operadores en expresiones compuestas. De todos modos, como en todos los lenguajes, se recomienda usar paréntesis en caso de duda.

Posfijos [] . (params) expr++ expr--

Operadores unarios ++expr --expr +expr -expr ~ !

Creación y "cast" new (type)

Multiplicativos * / %

Aditivos + -

Desplazamiento << >> >>>

Relacionales < > <= >= instanceof

Igualdad == !=

AND bit a bit &

OR exclusivo bit a bit ^

OR inclusivo bit a bit |

AND lógico &&

OR lógico ||

Condicional ? :

Asignación = += -= *= /= %= ^= &= |= <<= >>= >>>=

Algunos ejemplos:

[] define arreglos: int lista[];

(params) es la lista de parámetros cuando se llama a un método: convertir(valor, base);

new permite crear una instancia de un objeto: new Contador();

(type) cambia el tipo de una expresión a otro: (float)(total % 10);

>> desplaza bit a bit un valor binario: base >> 3;

<= devuelve "true" si un valor es menor o igual que otro: total <= maximo;

instanceof devuelve "true" si el objeto es una instancia de la clase: papa instanceof Comida;

|| devuelve "true" si cualquiera de las expresiones es verdad: (a<5) || (a>20)

Llamadas a métodos

Se llama a un método de la misma clase simplemente con el nombre del método y los parámetros entre paréntesis, como se ve, entre otros, en el ejemplo en negrita:

        // Archivo:    Complejo.java
        // Compilar con:       javac Complejo.java
        public final class Complejo extends Number {
        // atributos:
               private float x;
               private float y;
        // constructor:
public Complejo(float  rx, float iy) {
        x = rx;
        y = iy;
}
        // métodos:
               public float Norma() {
                       return (float)Math.sqrt(x*x+y*y);
               }
               // obligatorios (son abstractos en Number):
public double doubleValue() {
        return (double)Norma( );
}
public float floatValue() {
        return Norma();
}
public int intValue() {
        return (int)Norma();
}
public long longValue() {
        return (long)Norma();
}
public String toString() {
        return "("+x+")+i("+y+")";
}
        }

Pueden probar la clase (mínima) con el siguiente ejemplo de aplicación; la línea en negrita es un ejemplo de un llamado a un método de un objeto de otra clase. Notar que es este caso, es necesario llamar al método sobre un objeto (instancia) existente, por lo que se indica:

        Nombre_del_Objeto<punto>Nombre_del_Método(parámetros)
 
// Archivo:  Ejemplo4.java
// Compilar con: javac Ejemplo4.java
// Ejecutar con: java Ejemplo4
import java.io.*;
 
public class Ejemplo4 {
public static void main(String args[]) {
Complejo numComp = new Complejo(4,-3);
System.out.println(numComp.toString());
System.out.println(numComp.Norma());
}
}
 

En la clase Complejo tenemos también un ejemplo de un llamado a un método de clase, o sea static:

return (float)Math.sqrt(x*x+y*y);

Como el método es de clase, no hace falta llamarlo para un objeto en particular. En ese caso, en lugar del nombre de un objeto existente se puede utilizar directamente el nombre de la clase:

Nombre_de_la_Clase<punto>Nombre_del_Método(parámetros)

Práctica

Continuamos con la clase Persona:

Vamos a crear 4 métodos que permitan acceder a los atributos privados de la clase persona. Los agregamos dentro de la clase:

public int getEdad()

{

return edad;

}

public void setEdad(int laEdad)

{

edad = laEdad;

}

public String getNombre()

{

return nombre;

}

public void setNombre(String elNombre)

{

nombre = elNombre;

}

 

listaParámetros es la lista de los parámetros que tomará la función separados por comas y definidos cada uno de ellos como:

tipo nombreParámetro

modifFunción puede tener los siguientes valores:

static: el método pertenece a la clase, no a los objetos creados a partir de la clase.

final: el método no puede ser sobrescrito en una clase derivada.

abstract: En esta clase no se proporciona el código para la función, se debe de proporcionar en alguna clase derivada. En el caso de poseer un método abstracto la clase debe de llevar a su vez el modificador abstract. En caso de ser abstracto un método, se debe de sustituir las llaves que contienen el código por un punto y coma.

native: Es un método no escrito en java, sino en código nativo, que será usado en java como un método propio de java.

synchronized: Es un método que sólo puede ser ejecutado por un hilo, y hasta que ese hilo no acabe la llamada al método, no puede comenzar la llamada al método otro hilo. Lo emplearemos al trabajar con hilos.

La cláusula opcional throws es empleada para indicar que dentro del método se pueden generar errores en su ejecución, y que debemos estar preparados para tratarlos.

listaExcepciones es el nombre de todos esos posibles errores, su utilización la veremos en el punto dedicado a la gestión de errores mediante try y catch.

El método posee un par de llaves, dentro de las cuales estará el código que se ejecutará al ser llamada la función. Dicho código estará formado por instrucciones válidas en el lenguaje, finalizadas generalmente por punto y coma.

10.-DEFINA EL CONCEPTO DE PARAMETRO Y EXPLIQUE AMPLIAMENTE COMO SE UTILIZA:

 Un parametro es una variable que puede pasar su valor a un procedimiento desde el principal o desde otro procedimiento. Existen ocasiones en que es necesario mandar al procedimiento ciertos valores para que los use en algún proceso. Estos valores que se pasan del cuerpo principal del programa al procedimiento se llaman parametros. Entonces una declaracion completa es: Static void Nom Proc?(lista de parametros) { cuerpo de instrucciones; }; import java.lang.*; import java.io.*; class prog13 { public static void main(String[] args) {

// llamando procedimiento1 y pasando algunos parametros double beta=3.1416; proc1(8+4 , beta, “Jesus” ); }; // cierra main public static void proc1(int a, double b, String nom ) { double c = a + b; System.out.println(nom+ “ la suma fue =“ + c); }; // cierra proc } // cierra clase

REGLAS PARA EL USO DE PARAMETROS

1.- Cuando se usan variables como parametros, la variable que se manda debe ser declarada dentro del principal o del procedimiento de donde se esta enviando. 2.- La variable que se manda tiene un nombre, la que se recibe puede tener otro nombre. 3.- La cantidad de variables que se envian deben ser igual en cantidad, orden y tipo a las variables que reciben. 4.- La variable que recibe tiene un ambito local dentro del procedimiento, es decir solo la puede usar ese procedimiento. Y se pueden mandar datos, valores (excepto decimales), expresiones algebraicas, pero siempre se recibe en variables.

Los parametros de una función son los valores que esta recibe por parte del código que la llama. Pueden ser tipos simples u objetos.

En la declaración de la función se escriben después del nombre entre parentesis indicandose el tipo de cada uno y su nombre. Veamos esto a modo de ejempo:

   int dividir(int dividendo, int divisor) {

Está función recibe dos parámetros, ambos de tipo entero, uno el divisor y otro el dividendo.

A la hora de llamar a la función, los parametros se escriben también a continuación del nombre entre parentesis; pero en este caso no se indica el tipo de estos. Veamoslo en un ejemplo:

  int resultado = dividir(8,4);

En esta linea, se asigna a la variable entera resultado el retorno de la función dividir pasandole como parametros 8 y 4.

Es importante recordar que en java, los parametros de los tipos primitivos (int, long, etc.) SIEMPRE se pasan por valor. Los objetos se pasan por referencia.

En el paso de parámetros a funciones hay dos aproximaciones clásicas: el paso por valor y paso por referencia.

En el paso por valor se realiza una copia de los valores que se pasan, trabajando dentro de la función con la copia. Es por ello que cualquier cambio que sufran dentro, no repercute fuera de la función.

En el paso por referencia no se realiza dicha copia, por lo que las modificaciones de dentro de las funciones afectan a los parámetros y esos cambios permanecen al final de la función.

En Java el paso por parámetro es por valor, aunque los efectos son de paso por referencia cuando los argumentos son objetos. ¿cómo sucede eso? Pues es muy fácil, si una función tiene como argumento un tipo primitivo (int, float, etc...), en Java se realiza una copia para la función y cualquier cambio a dicho argumento no afecta a la variable original. Este paso de parámetros en Java está orientado a utilizar el valor de la variable para otros cálculos.

En el caso de los objetos es distinto. En realidad lo que sucede es que en Java siempre tenemos referencias a los objetos. Por eso al pasar a una función como argumento un objeto, pasamos la referencia al mismo, es decir, aunque se hace una copia para el paso por valor, como lo que se copia es una referencia, los cambios al objeto referenciado sí son visibles y afectan fuera de la función.

La única excepción es la clase String , cuyos objetos no son mutables. Cualquier modificación de un objeto String lleva aparejada la creación de una nueva instancia del objeto. Si deseamos el mismo comportamiento para el paso de parámetros del resto de objetos, tenemos que recurrir al objeto StringBuffer.

Un parametro es una variable que puede pasar su valor a un procedimiento desde el principal o desde otro procedimiento.

Existen ocasiones en que es necesario mandar al procedimiento ciertos valores para que los use en algún proceso.

Estos valores que se pasan del cuerpo principal del programa al procedimiento se llaman parametros.

Entonces una declaracion completa es:

void NomProc(lista de parametros)

{ cuerpo de instrucciones; };

prog13.java

 

import java.io.*;

 

import javax.servlet.*;

 

import javax.servlet.http.*;

 

public class prog13 extends HttpServlet

 

{

 

PrintWriter pagina;

 

public void doGet (HttpServletRequest request,

 

HttpServletResponse response)

 

throws ServletException, IOException

 

{

 

pagina =response.getWriter();

 

response.setContentType("text/html");

 

pagina.println("<HTML>");

 

// llamando procedimiento1 y pasando algunos parametros

 

double beta=3.1416;

 

proc1(8+4 , beta, "juan" );

 

pagina.println("</HTML>");

 

pagina.close();

 

};

 

public void proc1(int a, double b, String nom )

 

{

 

double c = a + b;

 

pagina.println(nom+ " la suma fue =" + c);

 

};

 

public void destroy(){super.destroy();};

 

}

 REGLAS PARA EL USO DE PARAMETROS

1.- Cuando se usan variables como parametros, la variable que se manda debe ser declarada dentro del principal o del procedimiento de donde se esta enviando.

2.- La variable que se manda tiene un nombre, la que se recibe puede tener otro nombre.

3.- La cantidad de variables que se envian deben ser igual en cantidad, orden y tipo a las variables que reciben.

4.- La variable que recibe tiene un ambito local dentro del procedimiento, es decir solo la puede usar ese procedimiento.

Y se pueden mandar datos, valores(excepto decimales), expresiones algebraicas, pero siempre se recibe en variables.

TAREAS PROGRAMACION JAVA SERVLET

Capturar el nombre y las 3 calificaciones en un procedimiento, calcular promedio en un segundo, imprimir nombre y promedio en principal

Construir una tabla de multiplicar que el usuario indique captura y control de ciclo en el principal, calculo en un procedimiento.

Construir un procedimiento que reciba un numero entero y que mande llamar a un segundo procedimiento pasando el letrero “PAR O IMPAR”.

11.-TOMANDO EN CUENTA EL CONCEPTO DE PARAMETRO DE 5 EJMPLOS DE PROGRAMAS DONDE SE ENCUENTREN PARAMETROS DE ENTRADA Y DE SALIDA:


Existe comúnmente la creencia errónea de que en Java es posible pasar parámetros por referencia, y no es así. Java siempre pasa los parámetros por valor. Esta confusión se da debido a que todas las variables de objeto son referencias a objetos [1].
En el libro “The Java Programming Language” de Ken Arnold y James Gosling (autores de Java), sección 2.6.1., tenemos la siguiente cita: “There is exactly one parameter passing mode in Java - pass by value - and that helps keep things simple.” [2] (Existe un solo modo de paso de parámetros en Java – paso por valor – y eso ayuda a mantener las cosas simples.).

Antes de continuar, vamos a recordar cuáles son las definiciones de paso por valor y paso por referencia: [3]:

Paso por valor significa que cuando un argumento se pasa a una función, la función recibe una copia del valor original. Por lo tanto, si la función modifica el parámetro, sólo la copia cambia y el valor original permanece intacto.

Paso por referencia significa que cuando un argumento se pasa a una función, la función recibe la dirección de memoria del valor original, no la copia del valor. Por lo tanto, si la función modifica el parámetro, el valor original en el código que llamó a la función cambia.

Vamos a valernos de ejemplos para explicar el mecanismo con el que Java pasa parámetros a los métodos.

Tenemos el siguiente programa Java:

1 public class ValorOReferencia {
2
3 private String param1 = new String();
4
5 /** Creates a new instance of PassValueOrReference */
6 public ValorOReferencia(String param1) {
7 this.setParam1(param1);
8 }
9
10 public static void cambiarObjeto(ValorOReferencia objeto) {
11 objeto = new ValorOReferencia(”Este es un nuevo objeto.”);
12 System.out.println(”Luego de ”reasignar” pass: ” + objeto);
13 }
14
15 public static void cambiarParam1(ValorOReferencia objeto) {
16 objeto.setParam1(”Este es un nuevo valor para param1.”);
17 }
18
19 public static void main(String[] args) {
20 ValorOReferencia pass =
21 new ValorOReferencia(”Objeto inicial.”);
22 System.out.println(”Entender que Java pasa parámetros por valor: “);
23 System.out.println(”Antes de modificar pass es: ” + pass);
24 ValorOReferencia.cambiarObjeto(pass);
25 System.out.println(”De vuelta en main pass es: ” + pass);
26 System.out.println(”Ahora vamos a cambiar sólo param1:”);
28 ValorOReferencia.cambiarParam1(pass);
29 System.out.println(”De seguro param 1 ha cambiado: ” + pass);
30 System.out.println(”Parece difícil, pero no lo es.”);
31 }
32
33 public String getParam1() {
34 return param1;
35 }
36
37 public void setParam1(String param1) {
38 this.param1 = param1;
39 }
40
41 public String toString() {
42 return “[param1 = " + this.getParam1() + "]“;
43 }
44
45 }

Remitámonos a línea 20. Declaramos una variable pass, de tipo ValorOReferencia, con su único atributo param1 inicializado con el valor “Objeto inicial.”. En la línea 23, presentamos el objeto en pantalla, y se muestra el valor con el que fue declarado.

Salida del programa:

Entender que Java pasa parámetros por valor:
Antes de modificar pass es: [param1 = Objeto inicial.]

Ahora, en la línea 24 pasamos nuestra variable pass al método cambiarObjeto, método que tiene un parámetro formal de tipo ValorOReferencia. En dicho método, en la línea 11, se realiza una asignación

objeto = new ValorOReferencia("Este es un nuevo objeto.");

, se presenta el objeto “modificado” y el control regresa al método main.

Salida del programa:

Luego de "reasignar" pass: [param1 = Este es un nuevo objeto.]

Suponiendo que el paso de parámetros en Java fuera por referencia, la referencia pass apuntaría ahora a un nuevo objeto con el valor “Este es un nuevo objeto.”. Pero, al regresar al método main, en la línea 25, presentamos de nuevo pass, y vemos que el valor con el que fue originalmente declarado se mantiene.

Salida del programa

De vuelta en main() pass es: [param1 = Objeto inicial.]

Ahora, vamos a pasar pass y vamos a modificar solamente su único atributo. En la línea 28, pasamos pass al método cambiarParam1, en donde tenemos la sentencia

objeto.setParam1("Este es un nuevo valor para param1.");

en la línea 16. Así, se ha modificado el valor del atributo param1, y al volver al método main, presentamos pass otra vez:

Salida del programa:

Ahora vamos a cambiar sólo param1:
De seguro param 1 ha cambiado: [param1 = Este es un nuevo valor para param1.]
Parece difícil, pero no lo es.

Al ver esta última operación, quizá alguien pueda decir que Java sí pasa parámetros por referencia, ya que se modificó el atributo del objeto, pero estaría equivocado: ¿Por qué en cambiarObjeto la variable pass no sufre ninguna modificación, y en el método cambiarParam1 su atributo se ve efectivamente modificado? Porque Java no pasa objetos como parámetros [4], sino copias de las referencias a esos objetos. Exacto. Java pasa parámetros por valor. Pasa referencias a objetos por valor.

Vamos a explicar lo que hacen nuestros métodos cambiarObjeto(ValorOReferencia objeto) y cambiarParam1(ValorOReferencia objeto).

cambiarObjeto(ValorOReferencia objeto)

En main, declaramos una variable

ValorOReferencia pass = new ValorOReferencia("Objeto inicial.");

Se ha creado un objeto ValorOReferencia en cierta posición de memoria y la forma de acceder a él es usar la referencia pass.

Omito los métodos setters, getters y toString() en el diagrama porque no intervienen en la explicación de este método. Este método tiene un parámetro formal ValorOReferencia objeto. Como Java pasa parámetros por valor tenemos que objeto, el parámetro formal de cambiarObjeto, es una copia de la referencia pass, es un alias, mas no es la referencia pass. Siguiente a la llamada al método lo que tenemos es lo siguiente:

objeto es una copia de la referencia pass, es otra referencia que apunta al mismo lugar. Al ejecutar la sentencia

objeto = new ValorOReferencia("Este es un nuevo objeto.");

lo que hacemos de hecho es esto:

objeto, que originalmente era una copia de la referencia pass, apunta ahora a un nuevo objeto creado en otra posición de memoria. Es por eso que de vuelta al main, el objeto apuntado por pass no ha cambiado.

cambiarParam1(ValorOReferencia objeto)

Desde el método main pasamos a cambiarParam1 la referencia pass:

Incluyo el método setter setParam1(String param1) porque interviene en esta explicación. cambiarParam1 tiene un parámetro formal ValorOReferencia objeto, que es un alias de pass.

Al ejecutar la sentencia

objeto.setParam1("Este es un nuevo valor para param1.");

, lo que estamos haciendo es invocar al método setParam1 del objeto apuntado por la referencia objeto. Es por eso que el atributo param1 del objeto referenciado por pass es efectivamente modificado.

Cuando declaramos variables, por ejemplo,

ValorOReferencia valoRef = new ValorOReferencia();

, no declaramos un objeto ValorOReferencia, sino una referencia a un objeto ValorOReferencia. Java tiene punteros (referencias a objetos), pero no es posible manejarlos con la aritmética con que se manejan en C++ [5]. No obstante, la implementación de estos punteros es similar en ambos lenguajes:

  • Una sentencia Java ValorOReferencia valORef; es exactamente igual a una sentencia C++ ValorOReferencia *valORef;.
  • Una sentencia Java valORef.cambiarParam1(“Otro valor.”); es exactamente igual a una sentencia C++ valORef -> cambiarParam1(“Otro valor.”);. [6]

Hay que tener claro entonces, que cuando se escribe una sentencia del estilo

cualquierFuncion(CualquierTipo argumento);

en Java, lo que se pasa no es un objeto, sino una copia de la referencia al objeto. Es importante no confundirnos. Java pasa objetos por referencia (pasa las referencias a los objetos), pero nunca pasa un objeto como parámetro [7], ni parámetros por referencia.

12.-DEFINA ELCONCEPTO DE "CONSTRUCTOR" Y EXPLIQUE AMPLIAMENTE PARA QUE SIRVE DENTRO DE UN PROGRAMA:

La función primordial del constructor es reservar memoria e inicializar las variables miembro de la clase.Los constructores no regresan valor, su parámetro implícito es el objeto que se está creando. Una clase puede tener varios constructores, cada uno con diferentes tipos y número de argumentos. Cuando una clase no tiene implementado un constructor entonces utiliza el constructor de la clase Object. El constructor de una subclase puede llamar al constructor de su superclase por medio de la palabra
reservada super, seguida de los argumentos entre paréntesis.

Sobrecarga de Constructores
Una clase puede tener más de un método constructor, los constructores siguen llevando el mismo nombre de la clase y ninguno regresa valores. Lo que marca la diferencia entre los constructores son los parámetros que recibe al momento de crear el objeto; esto es, el compilador utiliza el constructor apropiado de acuerdo a los parámetros que se escriban dentro de los paréntesis de new.


13.-MEDIANTE 5 EJEMPLOS DE PROGRAMACION SEÑALE Y EXPLIQUE EL O LOS CONSTRUCTORES UTILIZADOS:

Código Fuente Arboles.java.

 
public class Arboles  { 
 
    public Arboles() { 
      System.out.println("Un árbol genérico");
    }
  
    public Arboles(String tipo) {
     System.out.println("Un árbol tipo " + tipo);
    }
 
    public Arboles(int altura) {
     System.out.println("Un árbol de " + altura + " metros");
   }
 
    public Arboles(int altura,String tipo) { 
     System.out.println("Un " + tipo + " de " + altura + " metros");
   } 
  
    public static void main(String args[]) { 
        Arboles arbol1 = new Arboles(4);
        Arboles arbol2 = new Arboles("Roble");
        Arboles arbol3 = new Arboles();
        Arboles arbol4 = new Arboles(5,"Pino");

 

Clase Arboles

·         Como en todo programa Java , primeramente se define la Clase a través del vocablo class.

·         Posteriormente son definidos 4 Constructores; nótese que cada uno recibe el mismo nombre de la Clase y posee distintos argumentos de entrada.

·         Dentro del método principal (main) son generadas cuatro instancias de la Clase, como se puede observar, al ser generada la instancia a través del vocablo new se pasa un parámetro, y es dependiendo de este parámetro que es llamado el Constructor correspondiente, el cual a su vez invoca la Clase System.out.println que imprime a pantalla.

Constructor Obligatorio...

En los ejemplos anteriores del curso se pudo notar que no se hizo uso de Constructor alguno, y la razón es que el compilador lleva acabo esta definición de Constructor vacío detrás de los escenarios, sin embargo, existe una situación en la que es necesario definir un Constructor vacío y esta es cuando se hace uso de otros constructores.

Lo anterior significa que si el compilador observa un método con el mismo nombre de la clase con argumentos (Constructor), deberá existir un método vacío por el mismo nombre, esto de cierta manera salvaguarda a un programador al momento de definir métodos que no vayan a ser definidos erróneamente como Constructores

Tanto Java como C++ soportan la sobrecarga de métodos, es decir, que dos o más métodos puedan tener el mismo nombre, pero distinta lista de argumentos en su invocación. Si se sobrecarga un método, el compilador determinará ya en tiempo de compilación, en base a lista de argumentos con que se llame al método, cual es la versión del método que debe utilizar.

Tanto Java como C++ soportan la noción de constructor. El constructor es un tipo específico de método que siempre tiene el mismo nombre que la clase y se utiliza para construir objetos de esa clase. No tiene tipo de dato específico de retorno, ni siquiera void. Esto se debe a que el tipo específico que debe devolver un constructor de clase es el propio tipo de la clase.

En este caso, pues, no se puede especificar un tipo de retorno, ni se puede colocar ninguna sentencia que devuelva un valor. Los constructores pueden sobrecargarse, y aunque puedan contener código, su función primordial es inicializar el nuevo objeto que se instancia de la clase. En C++, el constructor se invoca automáticamente a la hora de crear un objeto. En Java, ha de hacerse una llamada explícita al constructor para instanciar un nuevo objeto.

Cuando se declara una clase en Java, se pueden declarar uno o más constructores opcionales que realizan la inicialización cuando se instancia (se crea una ocurrencia) un objeto de dicha clase.

Utilizando el código de la sección anterior, cuando se crea una nueva instancia de MiClase, se crean (instancias) todos los métodos y variables, y se llama al constructor de la clase:

    MiClase mc;
    mc = new MiClase();

La palabra clave new se usa para crear una instancia de la clase. Antes de ser instanciada con new no consume memoria, simplemente es una declaración de tipo. Después de ser instanciado un nuevo objeto mc, el valor de i en el objeto mc será igual a 10. Se puede referenciar la variable (de instancia) i con el nombre del objeto:

    mc.i++; // incrementa la instancia de i de mc

Al tener mc todas las variables y métodos de MiClase, se puede usar la primera sintaxis para llamar al método Suma_a_i() utilizando el nuevo nombre de clase mc:

    mc.Suma_a_i( 10 );

y ahora la variable mc.i vale 21.

Luego, en Java, cuando se instancia un objeto, siempre se hace una llamada directa al constructor como argumento del operador new. Este operador se encarga de que el sistema proporcione memoria para contener al objeto que se va a crear.

En C++, los objetos pueden instanciarse de diferentes formas, pero en Java solamente se pueden instanciar en la pila de memoria, es decir, solamente se pueden instanciar utilizando el operador new para poder solicitar memoria al sistema en tiempo de ejecución y utilizar el constructor para instanciar el objeto en esa zona de memoria. Si al intentar instanciar un objeto, la Máquina Virtual Java (JVM) no puede localizar la memoria que necesita ese objeto, bien inmediatamente o haciendo ejecutarse al reciclador de memoria, el sistema lanzará un OutOfMemoryError.

Tanto en Java como en C++, si no se proporciona explícitamente un constructor, el sistema proporciona uno por defecto que inicializará automáticamente todas las variables miembro a cero o su equivalente, en Java. En C++, el constructor de defecto no realiza ningún tipo de inicialización.

Se puede pensar en el constructor de defecto en Java como un método que tiene el mismo nombre que la clase y una lista de argumentos vacía. Y en C++, el constructor de defecto sería como la llamada cuando se instancia un objeto sin parámetros

    MiClase objeto;

En ambos lenguajes, si se proporciona uno o más constructores, el constructor de defecto no se proporciona automáticamente y si fuese necesaria su utilización, tendría que proporcionarlo explícitamente el programa.

Las dos sentencias siguientes muestran cómo se utiliza el constructor en Java para declarar, instanciar y, opcionalmente, inicializar un objeto:

    MiClase miObjeto = new MiClase();
    MiClase miObjeto = new MiClase( 1,2,3 );

Las dos sentencias devuelven una referencia al nuevo objeto que es almacenada en la variable miObjeto. También se puede invocar al constructor sin asignar la referencia a una variable. Esto es útil cuando un método requiere un objeto de un tipo determinado como argumento, ya que se puede incluir una llamada al constructor de este objeto en la llamada al método:

    miMetodo( new MiConstructor( 1,2,3 ) );

Aquí se instancia e inicializa un objeto y se pasa a la función. Para que el programa compile adecuadamente, debe existir una versión de la función que espere recibir un objeto de ese tipo como parámetro.

Tanto en Java como en C++, cuando un método o una función comienza su ejecución, todos los parámetros se crean como variables locales automáticas. En este caso, el objeto es instanciado en conjunción con la llamada a la función que será utilizada para inicializar esas variables locales cuando comience la ejecución y luego serán guardadas. Como son automáticas, cuando el método concluye su ejecución, se destruirá (en C++) o será marcado para su destrucción (en Java).

En el siguiente ejemplo, java507.java, se ilustran algunos de los conceptos sobre constructores que se han planteado en esta sección.

class MiClase {
    int varInstancia;
      
    // Este es el constructor parametrizado
    MiClase( int dato ) {
        // rellenamos la variable de instancia con los datos
        // que se pasan al constructor
        varInstancia = dato;
        }
      
    void verVarInstancia() {
        System.out.println( "El Objeto contiene " + varInstancia );
        }
    }
      
class java507 { 
    public static void main( String args[] ) {
        System.out.println( "Lanzando la aplicacion" );
        // Instanciamos un objeto de este tipo llamando al
        // constructor de defecto
        java507 obj = new java507();
        // Llamamos a la funcion pasandole un constructor
        // parametrizado como parametro
        obj.miFuncion( new MiClase( 100 ) );
        }
      
    // Esta funcion recibe un objeto y llama a uno de sus metodos
    // para presentar en pantalla el dato que contiene el objeto
    void miFuncion( MiClase objeto){
        objeto.verVarInstancia();
        }
    }

Herencia

En casos en que se vea involucrada la herencia, los constructores toman un significado especial porque lo normal es que la subclase necesite que se ejecute el constructor de la superclase antes que su propio constructor, para que se inicialicen correctamente aquellas variables que deriven de la superclase. En C++ y Java, la sintaxis para conseguir esto es sencilla y consiste en incluir en el cuerpo del constructor de la subclase como primera línea de código la siguiente sentencia:

  super( parametros_opcionales );

Esto hará que se ejecute el constructor de la superclase, utilizando los parámetros que se pasen para la inicialización. En el código del ejemplo siguiente, java508.java, se ilustra el uso de esta palabra clase para llamar al constructor de la superclase desde una subclase.

class SuperClase {
    int varInstancia;
      
    // Es necesario proporcionar el constructor por defecto,que
    // es aquel que no tiene parametros de llamada
    SuperClase(){}
      
    // Este es el constructor parametrizado de la superclase
    SuperClase( int pDato ) {
        System.out.println( 
            "Dentro del constructor de la SuperClase" );
        varInstancia = pDato;
        }
      
    void verVarInstancia() {
        System.out.println( "El Objeto contiene " + varInstancia );
        }
    }
      
class SubClase extends SuperClase {
    // Este es el constructor parametrizado de la subclase
    SubClase( int bDato ) {    
        // La siguiente sentencia println no compila, la llamada
        // a super() debe estar al principio de un metodo en caso de
        // que aparezca
        // System.out.println( "En el constructor de la SubClase" );
      
        // Llamamos al constructor de la superclase
        super( bDato );
        System.out.println( 
            "Dentro del constructor de la SubClase" );
        }
    }
      
class java508 {
    public static void main( String args[] ) {
        System.out.println( "Lanzando la aplicacion" );
      
        // Instanciamos un objeto de este tipo llamando al
        // constructor de defecto
        java508 obj = new java508();
        // Llamamos a la funcion pasandole un constructor de la
        // subclase parametrizado como parametro
        obj.miFuncion( new SubClase( 100 ) );
        }
      
        // Esta funcion recibe un objeto y llama a uno de sus metodos
        // para presentar en pantalla el dato que contiene el objeto,
        // en este caso el metodo es heredado de la SuperClase
        void miFuncion( SubClase objeto ) {
            objeto.verVarInstancia();
        }
    }

Si super no aparece como primera sentencia del cuerpo de un constructor, el compilador Java inserta una llamada implícita, super(), al constructor de la superclase inmediata. Es decir, el constructor por defecto de la superclase es invocado automáticamente cuando se ejecuta el constructor para una nueva subclase, si no se especifica un constructor parametrizado para llamar al constructor de la superclase.

Control de Acceso

El control de acceso también tiene un significado especial cuando se trata de constructores. Aunque en otra sección se trata a fondo el tela del control de acceso en Java, con referencia a los constructores se puede decir que el control de acceso que se indique determina la forma en que otros objetos van a pode instanciar objetos de la clase. En la siguiente descripción, se indica cómo se trata el control de acceso cuando se tienen entre manos a los constructores:

private

Ninguna otra clase puede instanciar objetos de la clase. La clase puede contener métodos públicos, y estos métodos pueden construir un objeto y devolverlo, pero nadie más puede hacerlo.

protected

Solamente las subclases de la clase pueden crear instancias de ella.

public

Cualquier otra clase puede crear instancias de la clase.

package

Nadie desde fuera del paquete puede construir una instancia de la clase. Esto es útil si se quiere tener acceso a las clases del paquete para crear instancias de la clase, pero que nadie más pueda hacerlo, con lo cual se restringe quien puede crear instancias de la clase.

En Java y en C++, una instancia de una clase, un objeto, contiene todas las variables y métodos de instancia de la clase y de todas sus superclases. Sin embargo, los dos lenguajes soportan la posibilidad de sobreescribir un método declarado en una superclase, indicando el mismo nombre y misma lista de argumentos; aunque los procedimientos para llevar a cabo esto son totalmente diferentes en Java y en C++.

Como aclaración a terminología que se empleo en este documento, quiero indicar que cuando digo sobrecargar métodos, quiero decir que Java requiere que los dos métodos tengan el mismo nombre, devuelvan el mismo tipo, pero tienen una diferente lista de argumentos. Y cuando digo sobreescribir métodos, quiero decir que Java requiere que los dos métodos tengan el mismo nombre, mismo tipo de retorno y misma lista de argumentos de llamada.

En Java, si una clase define un método con el mismo nombre, mismo tipo de retorno y misma lista de argumentos que un método de una superclase, el nuevo método sobreescribirá al método de la superclase, utilizándose en todos los objetos que se creen en donde se vea involucrado el tipo de la subclase que sobreescribe el método.

Finalizadores

Java no utiliza destructores (al contrario que C++) ya que tiene una forma de recoger automáticamente todos los objetos que se salen del alcance. No obstante proporciona un método que, cuando se especifique en el código de la clase, el reciclador de memoria (garbage collector) llamará:

    // Cierra el canal cuando este objeto es reciclado
    protected void finalize() {
        close();
        }

Cada objeto tiene el método finalize(), que es heredado de la clase Object. Si se necesitase realizar alguna limpieza asociada con la memoria, se puede sobreescribir el método finalize() y colocar en él el código que sea necesario.

Los programadores C++ deben tener en cuenta que el método finalize() no es un destructor. En C++, si existe un destructor, éste será invocado siempre que el objeto se salga de ámbito o vaya a ser destruido. En Java, aunque el método finalize() siempre se invocará antes de que el reciclador de memoria libere la zona de memoria ocupada por el objeto, no hay garantía alguna de que el reciclador de memoria reclame la memoria de un determinado objeto, es decir, no hay garantía de que el método finalize() sea invocado.

La regla de oro a seguir es que no se debe poner ningún código que deba ser ejecutado en el método finalize(). Por ejemplo, si se necesita concluir la comunicación con un servidor cuando ya no se va a usar un objeto, no debe ponerse el código de desconexión en el método finalize(), porque puede que nunca se llamado. Luego, en Java, es responsabilidad del programador escribir métodos para realizar limpieza que no involucre a la memoria ocupada por el objeto y ejecutarlos en el instante preciso. El método finalize() y el reciclador de memoria son útiles para liberar la memoria de la pila y debería restringirse su uso solamente a eso, y no depender de ellos para realizar ningún otro tipo de limpieza.

No obstante, Java dispone de dos métodos para asegurar que los finalizadores se ejecuten. Los dos métodos habilitan la finalización a la salida de la aplicación, haciendo que los finalizadores de todos los objetos que tengan finalizador y que todavía no hayan sido invocados automáticamente, se ejecuten antes de que la Máquina Virtual Java concluya la ejecución de la aplicación. Estos dos métodos son:

runFinalizersOnExit( boolean ), método estático de java.lang.Runtime, y

runFinalizersOnExit( boolean ), método estático de java.lang.System

Una clase también hereda de sus superclase el método finalize(), y en caso necesario, debe llamarse una vez que el método finalize() de la clase haya realizado las tareas que se le hayan encomendado, de la forma:

    super.finalize();

En la construcción de un objeto, se desplaza uno por el árbol de jerarquía, de herencia, desde la raíz del árbol hacia las ramas, y en la finalización, es al revés, los desplazamientos por la herencia debe ser desde las ramas hacia las superclases hasta llegar a la clase raíz.

14.-DEFINA EL CONCEPTO DE "DESTRUCTOR" Y EXPLIQUE AMPLIAMENTE PARA QUE SIRVE DENTRO DE UN PROGRAMA:

En Java no hay destructores como en C++. El sistema se ocupa automáticamente de liberar la memoria de los objetos que ya han perdido la referencia, por ejemplo cuando se termina el bloque en el que habían sido creados; porque a la referencia se le ha asignado el valor null o porque a la referencia se le ha asignado la dirección de otro objeto. A esta característica de Java se le llama garbage collection.
En Java no se sabe exactamente cuándo se va a activar el garbage collector, si no hay falta memoria es posible que no se llegue a activar. Se puede llamar al garbage collector con el método System.gc(), aunque el sistema considera esto sólo como una “sugerencia” a la JVM.


15.-MEDIANTE 5 EJEMPLOS DE PROGRAMACION SEÑALE Y EXPLIQUE EL O LOS DESTRUCTORES UTILIZADOS:
Destructores

void __destruct ( void )

PHP 5 introduce un concepto de destructor similar a aquellos de otros lenguajes de programación orientada a objetos, tal como C++. El método destructor será llamado tan pronto como todas las referencias a un objeto en particular sean removidas o cuando el objeto sea explícitamente destruido.

Ejemplo de Destructor

<?php
class MyDestructableClass {
   function
__construct() {
       print
"In constructorn";
       
$this->name = "MyDestructableClass";
   }

   function
__destruct() {
       print
"Destroying " . $this->name . "n";
   }
}

$obj = new MyDestructableClass();
?>

Como los constructores, los destructores de la clase padre no serán llamados explícitamente por el compilador. Para ejecutar un destructor padre, se debe tener una llamada explícita a parent::__destruct() en el cuerpo del destructor.

Nota: El destructor es llamado durante la finalización del script, de tal manera que los headers ya han sido enviados.

Nota: Intentar arrojar una excepción desde un destructor produce un error fatal.

Ejemplo

En el siguiente ejemplo se crean tres clases que forman una cadena de herencia. La clase First es la clase base, Second se deriva de First y Third se deriva de Second. Las tres tienen destructores. En Main(), se crea una instancia de la clase más derivada. Cuando ejecute el programa, observe que se llama a los destructores de las tres clases automáticamente y en orden, desde la más derivada hasta la menos derivada.

 

 

   

class First

{

    ~First()

    {

        System.Console.WriteLine("First's destructor is called");

    }

}

 

class Second: First

{

    ~Second()

    {

        System.Console.WriteLine("Second's destructor is called");

    }

}

 

class Third: Second

{

    ~Third()

    {

        System.Console.WriteLine("Third's destructor is called");

    }

}

 

class TestDestructors

{

    static void Main()

    {

        Third t = new Third();

    }

}

Resultados

Third's destructor is called

Second's destructor is called

First's destructor is called

 

C#

Copiar código

class First

{

    ~First()

    {

        System.Console.WriteLine("First's destructor is called");

    }

}

 

class Second: First

{

    ~Second()

    {

        System.Console.WriteLine("Second's destructor is called");

    }

}

 

class Third: Second

{

    ~Third()

    {

        System.Console.WriteLine("Third's destructor is called");

    }

}

 

class TestDestructors

{

    static void Main()

    {

        Third t = new Third();

    }

}

 

 

 Resultados

Third's destructor is called

Second's destructor is called

First's destructor is called

La destrucción del objeto’ a.) La destrucción de los objetos

Cuando un objeto no va a ser utilizado, el espacio de memoria de dinámica que utiliza ha de ser liberado, así como los recursos que poseía, permitiendo al programa disponer de todos los recursos posibles. A esta acción se la da el nombre de destrucción del objeto.

En Java la destrucción se puede realizar de forma automática o de forma personalizada, en función de las características del objeto.

b.) La destrucción por defecto: Recogida de basura

El intérprete de Java posee un sistema de recogida de basura, que por lo general permite que no nos preocupemos de liberar la memoria asignada explícitamente.

El recolector de basura será el encargado de liberar una zona de memoria dinámica que había sido reservada mediante el operador new, cuando el objeto ya no va a ser utilizado más durante el programa (por ejemplo, sale del ámbito de utilización, o no es referenciado nuevamente).

El sistema de recogida de basura se ejecuta periódicamente, buscando objetos que ya no estén referenciados.

c.) La destrucción personalizada: finalize

A veces una clase mantiene un recurso que no es de Java como un descriptor de archivo o un tipo de letra del sistema de ventanas. En este caso sería acertado el utilizar la finalización explícita, para asegurar que dicho recurso se libera. Esto se hace mediante la destrucción personalizada, un sistema similar a los destructores de C++.

Para especificar una destrucción personalizada se añade un método a la clase con el nombre finalize:

class Clase Finalizada?{

  Clase Finalizada() { // Constructor

    // Reserva del recurso no Java o recurso compartido

  }

  protected void finalize() {

    // Liberación del recurso no Java o recurso compartido

  }

}

El intérprete de Java llama al método finalize(), si existe cuando vaya a reclamar el espacio de ese objeto, mediante la recogida de basura.
Debe observarse que el método finalize () es de tipo protected void y por lo tanto deberá de sobreescribirse con este mismo tipo.
Un destructor es un método que pertenece a una clase y el mismo (en C++) debe tener el mismo nombre de la clase a la que pertenece. A diferencia de los otros métodos de la clase, un destructor deberá ser del tipo void, es decir, el mismo no regresará valor alguno. Para diferenciar a un método destructor de un método constructor, al nombre del destructor se le debe anteponer el caracter
~ (Alt + 126).

El objetivo principal del destructor es el de retirar de la memoria al objeto, o sea, el destructor hace todo lo contrario que el constructor.

Los destructores suelen usarse para liberar memoria que haya sido solicitada por el objeto a travez de las ordenes malloc(), new, etc. En tales casos se deberá incluir dentro del método destructor la orden free, delete, etc., según sea el caso.

// clase Pareja con constructor y destructor

class Pareja

{

    // atributos

    double a, b;

 

public:

    // constructor de base ( nulo )

    Pareja() {}

 

    // constructror parametrizado

    Pareja(double x, double y) : a(x), b(y) {}

 

    // destructor

    ~Pareja() {}

 

    // métodos

    double getA();

    double getB();

    void   setA(double n);

    void   setB(double n);

};

 
jose alfredo ocaña dolores
 
REPRODUCTOR DE MUSICA
 


Get Music Tracks! Make Your Own!

CONTADOR DE VISITAS
 
CHECA ELCLIMA EN TU LOCALIDAD
 
DEJA TU MENSAJE O COMENTARIO
 
 
Hoy habia 9518 visitantes¡Aqui en esta página!
Este sitio web fue creado de forma gratuita con PaginaWebGratis.es. ¿Quieres también tu sitio web propio?
Registrarse gratis