Ahora que sabes de Herencia y modificadores de acceso es momento de
ver dos palabras reservadas bastante importantes this y super. this y
super son palabras reservadas utiles en el contexto de la herencia para
referirse a los componentes de las clases que componen una estructura
de herencia y esto es algo que debes recordar y de ser posible
tatuartelo en la parte baja de la espalda para llevarlo siempre y es que
this y super son útiles para acceder a los constructores de las clases
en la herencia lo que es vital cuando las clases no tiene constructores
por defecto.
Pero que quiere decir cada uno de estos modificadores.
el primer caso sucede cuando tenemos algo así;
public class UnaClase{
private int variable;
//las dos variable se llaman igual, renuncio esta es una vida que no merece ser vivida
public void setVariable(int variable){
variable++;
}
}
como puedes ver arriba la variable de clase y la de la función se llaman igual así que al hacer el ++ cual variable fue aumentada ????.
Por dominio la variable declarada en la función es a la que nos estamos refiriendo es decir que la que aumento fue la variable de la función y la variable de la clase esta intacta. Ahora como solventar este dilema variabilistico simple con la palabra reservada this.
this nos permite hacer cosas como estas
public void setVariable(int variable){
variable++;//aumentar la variable de función
this.variable++;//aumentar la variable de clase
this.variable=variable;//el uso mas común asignar la variable de función a la variable de clase
this.variable=variable/this.variable; //operar entre la variable de función y de clase
}
El segundo uso es acceder desde un constructor a o otro constructor de la misma clase, imagina que tienes una clase con un constructor muy especifico pero que a la vez se desea permitir inicializar la misma clase con una serie de variables por defecto
public class UnaClase{
private int variable;
private String variable2;
//constructor mucho muy especifico
public UnaClase(int variable,String variable2){
this.variable=variable;
this.variable2=variable2;
}
//constructor mucho muy generico
public UnaClase(){
this.variable=1;
this.variable2="string val";
}
}
Si miras con atención veras que los constructores tiene adentro código algo repetido lo que esta en contra de un principio de programación llamado DRY (do not repeat yourself) que significa no escribir dos veces el mismo código... y ahora quien podrá defendernos... yo el modificador colo.. diré this.
this sin argumentos se puede referir al constructor de la clase si se le llama como si este fuese una función así:
this();//esto se refiere al constructor vació o por defecto de esta misma clase
Importante esto solo se hace dentro de otro constructor no escribas this() o this("hola") por toda la clase o en cualquier método.
Importante el constructor debe existir
mejor ver un ejemplo para entenderlo, primero uno que funcione
public class UnaClase{
private int variable;
private String variable2;
//constructor mucho muy especifico
public UnaClase(int variable,String variable2){
this.variable=variable;
this.variable2=variable2;
}
//constructor mucho muy genérico
public UnaClase(){
this(1,"string val");//taran!!! listo llamo a un constructor desde otro enviandole valores por //defecto
}
}
Ahora lo que no se debe hacer:
1. solo puedo llamar constructores que existan y esta confusión siempre esta relacionada con el constructor por defecto así que ¿cuando existe y cuando no existe un constructor por defecto?
primero cuando existe: en estos dos casos
cuando no se escribe ningún constructor para la clase
public class UnaCalse{
private int variable;
public void metodo(){}
}
esta clase no define constructor alguno entonces el compilador le pone uno por defecto algo así
public UnaClase(){}//no es gran cosa pero permite instanciar la clase
cuando se especifica para ejecutar alguna acción al crear la clase
public class UnaCalse{
private int variable;
public UnaCalse(){//especifico el constructor
variable=1;//realizo cualquier operación por ejemplo inicializa una variable
}
public void metodo(){}
}
Ahora cuando no existe: si se especifica algún otro constructor y no se especifica el constructor por defecto decimos que la clase no tiene constructor vació o por defecto
public class UnaCalse{
private int variable;
public UnaCalse(int variable){//especifico un constructor con argumentos
this();//ERROR NADIE ESPECIFICO UN CONSTRUCTOR VACIÓ ESTO NO COMPILA
this.variable=variable;
}
public void metodo(){}
}
si existe un constructor con argumentos y deseo también tener un constructor vació debo especificar el constructor sin argumentos así;
public class UnaCalse{
private int variable;
public UnaCalse(){//CONSTRUCTOR VACIÓ, INÚTIL PERO EXISTE
}
public UnaCalse(int variable){//especifico un constructor con argumentos
this();//BIEN AHORA SI EXISTE
this.variable=variable;
}
public void metodo(){}
}
2. no llamar constructores en ciclos cerrados por ejemplo
public class UnaCalse{
private int variable;
public UnaCalse(){//constructor vació
this(1);
}
public UnaCalse(int variable){//especifico un constructor con argumentos
this();
}
public void metodo(){}
}
viendo este código que puede suceder al llamar cualquiera de los dos constructores...... pues algo así
UnaCalse() llama a UnaCalse(int variable) llama a UnaCalse() llama a UnaCalse(int variable) llama a
UnaCalse() llama a UnaCalse(int variable) llama a UnaCalse() llama a UnaCalse(int variable) llama a
UnaCalse() llama a UnaCalse(int variable) llama a UnaCalse() llama a UnaCalse(int variable) llama a
UnaCalse() llama a UnaCalse(int variable) llama a UnaCalse() llama a UnaCalse(int variable) llama a
si un ciclo infinito.
public class UnaCalsePadre{
private int variable;
public UnaCalsePadre(int variable){//especifico un constructor con argumentos
this variable=variable;
}
public void metodo(){}
}
public class UnaCalseHijo extends UnaCalsePadre{
private int variable;
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
//AQUI HAY UN ERROR QUE IMPIDE QUE ESTO COMPILE
//SI MIRAS LA CLASE PADRE NO TIENE CONSTRUCTOR VACIÓ
//Y AQUI ESTOY TRATANDO DE LLAMAR DE FORMA IMPLÍCITA
//UN CONSTRUCTOR VACIÓ QUE NO EXISTE
this variable=variable;
}
public void metodo(){}
}
En este caso es cuando super entra en acción. Super al igual que this permite invocar el constructor de una clase en este caso el constructor de la super clase arreglando el problema de la siguiente forma.
public class UnaCalseHijo extends UnaCalsePadre{
private int variable;
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
super(variable);//ARREGLADO AQUÍ SUPER PERMITE LLAMAR A UN CONSTRUCTOR //LEGITIMO
this variable=variable;
}
public void metodo(){}
}
IMPORTANTE LOS LLAMADOS A LOS CONSTRUCTORES SUPER Y THIS SIEMPRE DEBEN SER LO PRIMERO EN HACERSE EN UN CONSTRUCTOR!!!!
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
super(variable);//BIEN
this variable=variable;
}
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
this variable=variable;
super(variable);//MAL!!!!
}
Segundo uso para super llamar las variables y métodos de una clase padre con el operador ".". El punto permite llamar los métodos y variables de instancia de la superclase ejemplo.
public class UnaCalseAbuelo{
public int variable;
public void metodo(){}
public void metodo1(){}
}
public class UnaCalsePadre{
public int variable;
public UnaCalsePadre(int variable){//especifico un constructor con argumentos
this variable=variable;
}
public void metodo(){}
}
public class UnaCalseHijo extends UnaCalsePadre{
public int variable;
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
super(varialbe) this variable=variable;
}
public void metodo(){
//como no hay otra variable en el dominio de función me refiero a la variable de esta clase
variable=1;
//this se refiere a la variable de esta clase
this.variable=1;
// super se refiere a la herencia en esta caso a la variable en la clase UnaCalsePadre
super.variable=1;
//metodo se refiere al metodo en el que estoy en esta clase es igual a decir this.metodo();
metodo();
//aqui me refiero al metodo en la clase UnaCalsePadre
super.metodo();
//aqui me refiero al metodo en esta misma clase
metodo1();
//aqui me regreso toda la herencia hasta encontrar el metodo1() en la clase UnaCalseAbuelo
super.metodo1();
//la diferencia esta en que el metodo() fue sobre escrito en UnaCalsePadre pero metodo1() no
}
public void metodo1(){}
}
Aquí termina la primera parte de this y super, diría que es todo pero no si miras bien aquí solo tenemos variables y métodos públicos, pero ¿como funcionan las cosas cuando las variables y los métodos tienen otros accesos como private, protected y default?
eso se vera en this super 2 "la venganza de cal-el" (click aqui)
Pero que quiere decir cada uno de estos modificadores.
this; se refiere a la clase en la que estoy por lo general se usa para evitar la ambigüedad (cuando dos variables se llaman igual) o para acceder a los constructores de la misma clase.
el primer caso sucede cuando tenemos algo así;
public class UnaClase{
private int variable;
//las dos variable se llaman igual, renuncio esta es una vida que no merece ser vivida
public void setVariable(int variable){
variable++;
}
}
como puedes ver arriba la variable de clase y la de la función se llaman igual así que al hacer el ++ cual variable fue aumentada ????.
Por dominio la variable declarada en la función es a la que nos estamos refiriendo es decir que la que aumento fue la variable de la función y la variable de la clase esta intacta. Ahora como solventar este dilema variabilistico simple con la palabra reservada this.
this nos permite hacer cosas como estas
public void setVariable(int variable){
variable++;//aumentar la variable de función
this.variable++;//aumentar la variable de clase
this.variable=variable;//el uso mas común asignar la variable de función a la variable de clase
this.variable=variable/this.variable; //operar entre la variable de función y de clase
}
El segundo uso es acceder desde un constructor a o otro constructor de la misma clase, imagina que tienes una clase con un constructor muy especifico pero que a la vez se desea permitir inicializar la misma clase con una serie de variables por defecto
public class UnaClase{
private int variable;
private String variable2;
//constructor mucho muy especifico
public UnaClase(int variable,String variable2){
this.variable=variable;
this.variable2=variable2;
}
//constructor mucho muy generico
public UnaClase(){
this.variable=1;
this.variable2="string val";
}
}
Si miras con atención veras que los constructores tiene adentro código algo repetido lo que esta en contra de un principio de programación llamado DRY (do not repeat yourself) que significa no escribir dos veces el mismo código... y ahora quien podrá defendernos... yo el modificador colo.. diré this.
this sin argumentos se puede referir al constructor de la clase si se le llama como si este fuese una función así:
this();//esto se refiere al constructor vació o por defecto de esta misma clase
Importante esto solo se hace dentro de otro constructor no escribas this() o this("hola") por toda la clase o en cualquier método.
Importante el constructor debe existir
mejor ver un ejemplo para entenderlo, primero uno que funcione
public class UnaClase{
private int variable;
private String variable2;
//constructor mucho muy especifico
public UnaClase(int variable,String variable2){
this.variable=variable;
this.variable2=variable2;
}
//constructor mucho muy genérico
public UnaClase(){
this(1,"string val");//taran!!! listo llamo a un constructor desde otro enviandole valores por //defecto
}
}
Ahora lo que no se debe hacer:
1. solo puedo llamar constructores que existan y esta confusión siempre esta relacionada con el constructor por defecto así que ¿cuando existe y cuando no existe un constructor por defecto?
primero cuando existe: en estos dos casos
cuando no se escribe ningún constructor para la clase
public class UnaCalse{
private int variable;
public void metodo(){}
}
esta clase no define constructor alguno entonces el compilador le pone uno por defecto algo así
public UnaClase(){}//no es gran cosa pero permite instanciar la clase
cuando se especifica para ejecutar alguna acción al crear la clase
public class UnaCalse{
private int variable;
public UnaCalse(){//especifico el constructor
variable=1;//realizo cualquier operación por ejemplo inicializa una variable
}
public void metodo(){}
}
Ahora cuando no existe: si se especifica algún otro constructor y no se especifica el constructor por defecto decimos que la clase no tiene constructor vació o por defecto
public class UnaCalse{
private int variable;
public UnaCalse(int variable){//especifico un constructor con argumentos
this();//ERROR NADIE ESPECIFICO UN CONSTRUCTOR VACIÓ ESTO NO COMPILA
this.variable=variable;
}
public void metodo(){}
}
si existe un constructor con argumentos y deseo también tener un constructor vació debo especificar el constructor sin argumentos así;
public class UnaCalse{
private int variable;
public UnaCalse(){//CONSTRUCTOR VACIÓ, INÚTIL PERO EXISTE
}
public UnaCalse(int variable){//especifico un constructor con argumentos
this();//BIEN AHORA SI EXISTE
this.variable=variable;
}
public void metodo(){}
}
2. no llamar constructores en ciclos cerrados por ejemplo
public class UnaCalse{
private int variable;
public UnaCalse(){//constructor vació
this(1);
}
public UnaCalse(int variable){//especifico un constructor con argumentos
this();
}
public void metodo(){}
}
viendo este código que puede suceder al llamar cualquiera de los dos constructores...... pues algo así
UnaCalse() llama a UnaCalse(int variable) llama a UnaCalse() llama a UnaCalse(int variable) llama a
UnaCalse() llama a UnaCalse(int variable) llama a UnaCalse() llama a UnaCalse(int variable) llama a
UnaCalse() llama a UnaCalse(int variable) llama a UnaCalse() llama a UnaCalse(int variable) llama a
UnaCalse() llama a UnaCalse(int variable) llama a UnaCalse() llama a UnaCalse(int variable) llama a
si un ciclo infinito.
super; se refiere a las clases mas inmediatas en la herencia y se usa para acceder a variables, funciones y constructores en la clase padre.
El primer caso es acceder al constructor de la clase padre, llamar al constructor de la clase padre es lo que debe hacer toda clase al ser instanciada y así no se especifique siempre lo va a hacer. Pero hay un problema ¿que pasa cuando la clase padre no tiene un constructor por defecto? ejemplo:public class UnaCalsePadre{
private int variable;
public UnaCalsePadre(int variable){//especifico un constructor con argumentos
this variable=variable;
}
public void metodo(){}
}
public class UnaCalseHijo extends UnaCalsePadre{
private int variable;
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
//AQUI HAY UN ERROR QUE IMPIDE QUE ESTO COMPILE
//SI MIRAS LA CLASE PADRE NO TIENE CONSTRUCTOR VACIÓ
//Y AQUI ESTOY TRATANDO DE LLAMAR DE FORMA IMPLÍCITA
//UN CONSTRUCTOR VACIÓ QUE NO EXISTE
this variable=variable;
}
public void metodo(){}
}
En este caso es cuando super entra en acción. Super al igual que this permite invocar el constructor de una clase en este caso el constructor de la super clase arreglando el problema de la siguiente forma.
public class UnaCalseHijo extends UnaCalsePadre{
private int variable;
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
super(variable);//ARREGLADO AQUÍ SUPER PERMITE LLAMAR A UN CONSTRUCTOR //LEGITIMO
this variable=variable;
}
public void metodo(){}
}
IMPORTANTE LOS LLAMADOS A LOS CONSTRUCTORES SUPER Y THIS SIEMPRE DEBEN SER LO PRIMERO EN HACERSE EN UN CONSTRUCTOR!!!!
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
super(variable);//BIEN
this variable=variable;
}
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
this variable=variable;
super(variable);//MAL!!!!
}
Segundo uso para super llamar las variables y métodos de una clase padre con el operador ".". El punto permite llamar los métodos y variables de instancia de la superclase ejemplo.
public class UnaCalseAbuelo{
public int variable;
public void metodo(){}
public void metodo1(){}
}
public class UnaCalsePadre{
public int variable;
public UnaCalsePadre(int variable){//especifico un constructor con argumentos
this variable=variable;
}
public void metodo(){}
}
public class UnaCalseHijo extends UnaCalsePadre{
public int variable;
public UnaCalseHijo (int variable){//especifico un constructor con argumentos
super(varialbe) this variable=variable;
}
public void metodo(){
//como no hay otra variable en el dominio de función me refiero a la variable de esta clase
variable=1;
//this se refiere a la variable de esta clase
this.variable=1;
// super se refiere a la herencia en esta caso a la variable en la clase UnaCalsePadre
super.variable=1;
//metodo se refiere al metodo en el que estoy en esta clase es igual a decir this.metodo();
metodo();
//aqui me refiero al metodo en la clase UnaCalsePadre
super.metodo();
//aqui me refiero al metodo en esta misma clase
metodo1();
//aqui me regreso toda la herencia hasta encontrar el metodo1() en la clase UnaCalseAbuelo
super.metodo1();
//la diferencia esta en que el metodo() fue sobre escrito en UnaCalsePadre pero metodo1() no
}
public void metodo1(){}
}
Aquí termina la primera parte de this y super, diría que es todo pero no si miras bien aquí solo tenemos variables y métodos públicos, pero ¿como funcionan las cosas cuando las variables y los métodos tienen otros accesos como private, protected y default?
eso se vera en this super 2 "la venganza de cal-el" (click aqui)
Comentarios
Publicar un comentario