Modificador "Final"

Iniciado por Dem0ny, 15 Abril 2009, 13:38 PM

0 Miembros y 1 Visitante están viendo este tema.

Dem0ny

Bien, tengo una duda. Un colega y yo nos pusimos con un ejemplito basico y aver si me podeis echar un cable. Resulta que tengo una variable X de tipo int, y declarada como final, en una clase padre y por tanto por herencia, en una clase hija. A parte mandamos x a imprimirse en la clase principal y demas... blabla bla... simplemente para probar el modificador "Final" con herencia.

Nos dimos cuenta de que, al quitar el modificador "FINAL" en la clase padre, imprimia lo mismo!!.
Me quedé... :o. Pienso yo que no debería no? no debería crear un metodo constructor en el padre y luego mediante el uso de super() en la hija pillar ese constructor... para que resulte igual que el final?..

No entiendo porque sucede esto. Dejo un codigo de ejemplo:


Código (java) [Seleccionar]

class Prueba{
public static void main(String arg[]){
Padre obj1=new Padre();
Hija obj2= new Hija();
System.out.println("En el metodo principal, clase principal (Padre):  "+obj1.padre1());
System.out.println("En el metodo principal, clase principal (Hija): "+obj2.hija1());

}
}
class Padre{
    final int x=5;  //QUITANDO ESTE FINAL Y PONIENDOLO , RESULTA LO MISMO
public int padre1(){

System.out.println("Dentro de la clase Padre: "+x);
return x;

}
}
class Hija extends Padre{
public int hija1(){
System.out.println("Dentro de la clase hija: "+x);
return x+1;
}
}



Saludos!

juancho77

Cuál es el problema? Las variables FINAL pueden ser heredadas por clases hijas, pero no redefinidas ni modificadas.

Dem0ny

Exactamente, si, se heredan y no pueden modificarse en sí.

Lo que yo me refiero esque el código anterior... si eliminamos el modificador FINAL, me ejecuta el mismo codigo sin este modificador, cosa que no debería ser asi.

Observa el código:

Código (java) [Seleccionar]
class Prueba{
public static void main(String arg[]){
Padre obj1=new Padre();
Hija obj2= new Hija();
System.out.println("En el metodo principal, clase principal (Padre):  "+obj1.padre1());
System.out.println("En el metodo principal, clase principal (Hija): "+obj2.hija1());

}
}
class Padre{
    final int x=5;  //QUITANDO ESTE FINAL Y PONIENDOLO , RESULTA LO MISMO
public int padre1(){

System.out.println("Dentro de la clase Padre: "+x);
return x;

}
}
class Hija extends Padre{
public int hija1(){
System.out.println("Dentro de la clase hija: "+x);
return x+1;
}
}


Tenemos un programa nada mas que como ejempliyo del modificador FINAL. Pero... que ocurre si en la clase padre que está definido el modificador final, lo dejamos como:

Código (java) [Seleccionar]
class Padre{
  int x=5;  //QUITANDO ESTE FINAL Y PONIENDOLO , RESULTA LO MISMO
public int padre1(){

System.out.println("Dentro de la clase Padre: "+x);
return x;

}
}


en vez de:


Código (java) [Seleccionar]
class Padre{
    final int x=5;  //QUITANDO ESTE FINAL Y PONIENDOLO , RESULTA LO MISMO
public int padre1(){

System.out.println("Dentro de la clase Padre: "+x);
return x;

}
}


Lo curioso del programa esque al eliminar el modificador final te queda el mismo programa pero sin el modificador FINAL y Obtenemos el mismo resultado. Por ello, no me explico porque, si eliminamos este modificador, como si lo dejamos, obtenermos el mismo resultado

Según mi forma de verlo, en caso de que eliminaramos el modificador final de la variable x, sería un codigo que inicializara una variable en un metodo constructor de la clase padre y que mediante el uso de super(). Mandaríamos el constructor copiado a la hija, de tal forma, estaría usandose la variable X, mediante herencia y sin el uso de la particula final.


Despues de todo este royo, por si no lo has entendio: Jjaja, sorry por no explicarme bien: Si tienes el codigo anterior y eliminas FINAL, te resulta lo mismo que si lo mantienes. XD

Un saludo y gracias!










juancho77

Es que no deberia modificar nada en ESE programa. El modificador final sirve para proteger variables para que no sean malusadas cuando necesitas usar herencia. Por ejemplo, si muchas variables de clases criticas asociadas al SO no fueran final, cualquier persona podria modificarlas y usar de forma indebida procesos criticos. Me explico? Prueba esto y veras la diferencia:




Código (java) [Seleccionar]
public class padre {
protected final int x;
public padre()
{
x=5;
}
}



public class hija extends padre {

public static void main(String[]args)
{
hija h=new hija();
h.main();
}
public void main()
{
System.out.println(++x);
}
}


Si intentas modificar la variable declarada como final, el compilador te tira un error "padre.x cannot be assigned or modified". En cambio, si borras el final, podras modificarla a gusto. Ese es el trabajo de FINAL.

Dem0ny

Cita de: juancho77 en 18 Abril 2009, 22:35 PM
Es que no deberia modificar nada en ESE programa. El modificador final sirve para proteger variables para que no sean malusadas cuando necesitas usar herencia. Por ejemplo, si muchas variables de clases criticas asociadas al SO no fueran final, cualquier persona podria modificarlas y usar de forma indebida procesos criticos. Me explico? Prueba esto y veras la diferencia:




Código (java) [Seleccionar]
public class padre {
protected final int x;
public padre()
{
x=5;
}
}



public class hija extends padre {

public static void main(String[]args)
{
hija h=new hija();
h.main();
}
public void main()
{
System.out.println(++x);
}
}


Si intentas modificar la variable declarada como final, el compilador te tira un error "padre.x cannot be assigned or modified". En cambio, si borras el final, podras modificarla a gusto. Ese es el trabajo de FINAL.



Vale, he comprendido, porqué sucedía una cosa, pero esque no me he explicado correctamente, o no me comprendes jeje. Veamos he fracionado mis preguntas y gracias a tus respuestas he conseguido aclarar la mayoría de mis dudas.

En cuanto a tu codigo que me has puesto:

- ¿Porqué daría error en el println con ++x (Incremento) y con x+1 (incrementaria el valor igual). Acaso al incrementar, estes donde estés incluso en un print un incremento modifica la variable no solo en el print? Porque el x+1 imprime una unidad mas y no guarda en la variable x el valor?

- ¿El modificador publico en las clases padre e hija no sobraría?


En cuanto a mis dudas anteriores me gustaría preguntar:

-¿Porque no hace falta al eliminar el modificador FINAL crear un metodo constructor en la clase Padre? (ESTO EN MI CODIGO, DEL PRIMER POST)



Muchas gracias por tu ayuda! :)

juancho77

Bien, a ver, vamos paso a paso:

La funcion ++(variable) es una función unaria que se aplica a la variable. Entonces, al hacer ++x, estamos modificando el valor de x en una unidad. Seria equivalente a hacer x=x+1 o x+=1. Por eso, si haces un print con ++x, primero se modifica el valor y luego se imprime. En cambio, si llamas al print con x+1, se imprime el valor de x incrementado en 1, pero no se modifica la variable.

Si te refieres al modificador publico que inclui en mis clases: los inclui por costumbre. Si no pongo nada equivale a poner un protected.

Por ultimo, no hace falta poner ningun constructor al remover el final porque la variable de instancia x se inicializa igual en 5 en tu codigo. Ademas, la clase hija, si no se especifica ningun constructor, automaticamente llama a public hija() que ademas tiene un llamado a super().

Espero sirva. saludos.

Dem0ny

Okey, todo resuelto. Lo he comprendido y he resuelto todas mis dudas.

Gracias por todo juancho77 :D

Un saludo!