terça-feira, 8 de setembro de 2009

Métodos/Construtores,Sobrecarga,Sobrescrita,this, super

Sumário: Implementação de Métodos, Assinatura de um método, Sobrecarga(Overloading) de Métodos, Varargs, This, Sobrecarga de Construtores,Como invocar um Construtor dentro de outro Construtor da mesma classe,Como invocar Construtores da SuperClass,super, super(),Como invocar métodos da SuperClasse,Sobrescrita de Métodos.




Implementação de métodos:



Todo bloco de código de um método é considerado a implementação dele, vejamos o exemplo:

public void metodo( ){

//bloco de codigo

}

public void metodo2( ){
int variavel = 0;

//bloco de codigo
}

Logo acima temos 2 métodos com implementações de código diferente.


Assinatura de um método:

Quando você declara um método, você cria a assinatura do método, vejamos o exemplo:


public void metodo( ){

//bloco de codigo

}

A assinatura do método é:
public void metodo( )



Sobrecarga(Overloading) de Métodos:


Um método é considerado Sobrecarregado quando temos mais de um método com o mesmo identificador e ARGUMENTOS diferentes em (Quantidade, Ordem ou Tipo). Podemos escolher o uso de overload também para trabalhar com diferentes tipos de dados sobre o mesmo membro ou mesmo o quesito de mesmo identificador e diferente assinatura.

Vejamos exemplos de overload:


Assinatura de métodos:

public void metodo(int argumento)
public void metodo(byte argumento)
public void metodo(short argumento)

Perceba que eles tem o mesmo identificador, nesse caso - metodo - e tem argumentos diferente.
Na invocação do método, o compilador testará os parametros e escolherá de acordo com Parametros e argumentos dos métodos, a TIPAGEM(tipos de dados em java) de java agora sim é muito mais que util.


Oque realmente caracteriza métodos Overload?


- A lista de argumentos entre os método deve SER DIFERENTE isso é regra básica, se tiver o mesmo identificador e lista de Argumentos diferentes em: ORDEM e/ou TIPO e/ou QUANTIDADE, isso ja caracteriza OVERLOAD.

- O tipo de retorno pode ser diferente, SE OS MÉTODOS TIVEREM MESMO IDENTIFICADOR e lista de argumento diferentes em
ORDEM e/ou TIPO e/ou QUANTIDADE e ainda tiverem tipo de retorno diferente, isso é considerado ainda OVERLOAD.

Varargs:

Lembra-se do recurso de varargs?

[modificador_de_acesso] tipo_retorno identificador( tipo ... identificador )

Pois bem, ele é a mesma coisa que um overload contínuo de mesmo tipo, vejamos:

public void metodo(byte variavel)
public void metodo(byte variavel,byte variavel2)
public void metodo(byte variavel,byte variavel2, byte variavel3)

Ao invez disso podemos usar:

public void metodo(byte ... variavel)
Sendo assim podemos aceitar quantos parametros forem passados, independente da quantidade


This:


Basicamente ele :
*Resolve Ambiguidade
*Passar o objeto atual como Parametro
*Invocar um construtor da mesma classe

O this basicamente nada mais é doque a posição 0 da local variable, so que estamos usando explicitamente ele agora.
Quando você estiver trabalhando com instancias, é a mesma coisa que dizer, ESSE OBJETO, essa INSTANCIA QUE ESTOU AGORA.


Resolvendo ambiguidade:


public class Pessoa{
private int idade;


public void setIdade(int idade){
this.idade = idade;

}

}

Em sintax bytecode temos no Frame setIdade:
public void setIdade(int);
Code:
0: aload_0
1: iload_1
2: putfield #2; //Field idade:I
5: return

*aload_0 - > É uma referência a Constant Pool do Class File, que futuramente será a Runtime Constant Pool e com dynamic linking, será HEAP

}




Clique na imagem para ampliar
, nesse caso o int é (int idade), lembra-se que todo argumento é variavel local ao Frame? Pois bem, Quando os parametros forem passados ao frame setIdade serão armazenados como variável local ao frame, que nesse é a posição 1 da local variable.




Agora sem o this:

public class Pessoa{
private int idade;


public void setIdade(int idade){
idade = idade;

}

}


Em sintax bytecode temos no Frame setIdade: public void setIdade(int);
Code:
0: iload_1
1: istore_1
2: return

}






Clique na imagem para ampliar nesse caso o int é (int idade), lembra-se que todo argumento é variavel local ao Frame? Pois bem, Quando os parametros forem passados ao frame setIdade serão armazenados como variável local ao frame, que nesse é a posição 1 da local variable.



Passar o objeto atual:


public class Pessoa{

public void setIdade(){
setIdade2(this);

}

public void setIdade2(Pessoa pessoa){


}


public static void main(String array[]){
Pessoa my = new Pessoa();
my.setIdade();



}

}

Vejamos essa instrução:

setIdade2(this);

Basicamente aqui eu digo, pega o endereço de memória do OBJETO Que estou no momento e passa como parametros aos argumentos de
setIdade2(Pessoa pessoa).



Sobrecarga de Construtores:

Existe uma maneira a qual você pode construir seus objetos de acordo com os dados iniciais passados, As vezes em cadastro como exemplo não temos todos os dados em exato momento e esses dados não são tão importantes para a construção daquele objeto em si.

Vejamos exemplo:


Em uma loja virtual ao se cadastrar coloca-se alguns dados. Temos 2 participantes jose e maria, maria não sabe o numero da casa dela, mais não é tao importante nesse caso porem seria bom se tivesse. Vejamos em código:

public class Pessoa{

private String name;
private String endereco;
private int numeroCasa;


public Pessoa(String name,String endereco,int numeroCasa){ //jose invoca esse construtor
this.name = name;
this.endereco = endereco;
this.numeroCasa = numeroCasa;



}

public Pessoa(String name,String endereco){//maria invoca esse construtor
this.name = name;
this.endereco = endereco;

}



public static void main(String array[ ]){

Pessoa jose = new Pessoa("Jose","Rua São João",50);

Pessoa maria = new Pessoa("Maria","Rua das flores");


}

}

Veja que no exemplo acima, jose aciona um construtor enquanto maria aciona outro construtor diferente de jose. Existe uma verificação de Parametros e argumentos, e assim que é escolhido o mais indicado.


Como invocar um Construtor dentro de outro Construtor da mesma classe?


Usando a keyword this, A keyword this deve ser a primeira instrução de um construtor, Podemos ter instruções depois da instrução this, mais não antes.

Veja o exemplo:


public class Pessoa{

private String name;
private String endereco;
private int numeroCasa;


private Pessoa(String name,String endereco,int numeroCasa){
this.name= name;
this.endereco = endereco;
this.numeroCasa = numeroCasa;


}

public Pessoa(String name,String endereco){
this(name,endereco,0); // Primeira linha do construtor

}

}


public class Registro{


public static void main(String array[ ]){

Pessoa maria = new Pessoa("Maria","Rua das flores");
}



}

Nesse exemplo podemos perceber:
1 - Na classe Pessoa temos um construtor que tem modificador de acesso private, oque significa que o acesso a ele só é dado na MESMA CLASSE.
2 -
Na classe Pessoa temos um construtor que tem modificador de acesso public, oque permite o acesso EXTERNO a classe, e foi uque fiz na Classe Registro

Temos dois construtores com mesmo identificador porem com argumentos diferentes, oque CARACTERIZA Overload de Construtor.


Classe Pessoa:

O construtor de assinatura:

public Pessoa(String name,String endereco)
É invocado na Classe Registro pelo objeto maria, o construtor invoca outro construtor de assinatura:

private Pessoa(String name,String endereco,int numeroCasa)

E passa como parametro os que recebeu e mais um valor que foi colocado como default, que seria o endereço de casa(ou seja o 0 - ZERO).this(name,endereco,0); Como o construtor com modificador de acesso private so pode ser acessado pela mesma classe, foi isso que o construtor com modificador de acesso public fez, acessou ele de dentro da mesma classe.


Construtores são Herdados?

Não apenas membros de classe são herdados, Construtores não são membros.



Como invocar Construtores da SuperClass?

Usando a keyword super() na primeira linha do construtor da SubClass, Passa-se Parametros normais aos argumentos do construtor da SuperClass e
super() deve ser a primeira instrução do construtor da SubClass.

Vejamos o exemplo:

public class SuperClass{

public SuperClass(int variable){

}

}

public class SubClass extends SuperClass{

public SubClass( ){
super(10); //Invocando o Construtor da SuperClass

}


}


Herança e this,super,SuperClass:


Primeiro fundamento básico, toda classe quando não especificado explicitamente tem java.lang.Object como SuperClasse Direta.
Segundo fundamente básico, todo objeto criado a partir de um SubClasse também cria um objeto que é tanto SubClasse quanto SuperClasse, isso quer dizer que ao invocar o construtor de uma SubClasse você explicitamente ou implicitamente também invoca o construtor da SuperClasse.



Vejamos:

public class Pessoa{

private String name;
private String endereco;
private int numeroCasa;


private Pessoa(String name,String endereco,int numeroCasa){
this.name= name;
this.endereco = endereco;
this.numeroCasa = numeroCasa;


}

public Pessoa(String name,String endereco){
this(name,endereco,0);

}



public static void main(String array[ ]){

Pessoa maria = new Pessoa("Maria","Rua das flores");


}

}

Perceba que a Classe pessoa explicitamente não é um Object, porem toda classe tem Object como SuperClasse seja Explicitamente ou Implicitamente E Diretamente ou Inderetamente, Vou provar isso através de bytecode.


Vejamos:

Logo no incio do arquivo.class temos:
Compiled from "Pessoa.java"
public class Pessoa extends java.lang.Object{

Ou seja esta PROVADO que toda classe tem Object como SuperClasse, seja indiretamente ou Diretamente, Implicitamente ou Explicitamente.

Agora dentro de qualquer um dos construtores da classe podemos Perceber que:


public Pessoa(java.lang.String, java.lang.String, int);
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."init>":()V

Essa linha de instrução
1: invokespecial #1; //Method java/lang/Object."init>":()V
Diz que ao cria-se um Objeto dessa classe também invoca-se o construtor da Classe Object. OQUE QUER DIZER QUE TODA VEZ QUE A JVM CRIA UMA INSTANCIA DA CLASSE ELA TAMBÉM CRIA UMA INSTANCIA DA SUPERCLASSE, SEJA IMPLICITAMENTE DITO COMO SUPER() OU EXPLICITAMENTE FEITO PELO COMPILADOR.


Oquer faz a palavra super sozinha?

Faz referência a SuperClasse da Classe na qual ela é usada, usando o Operador Ponto ou seja Notação de Ponto você pode acessar qualquer membro da SuperClasse. E usando super() com Parenteses você pode acessar o construtor da SuperClasse e entre os Parênteses passar os parametros devidos aos argumentos do construtor.


Como invocar métodos da SuperClasse?

Sabemos que herança significa que a SubClasse tem tudo que a SuperClasse tem porem, em alguns casos é viável para ECONOMIZAR código.


public class SuperDaSuper{


public String metodoSuper(){

return "SuperDaSuper";


}
}

public class SuperClasse extends SuperDaSuper{

public String metodoSuper(){

return super.metodoSuper() +" SuperClasse";


}

}



public class SubClasse extends SuperClasse{


public String up(){

return super.metodoSuper() +" SubClasse";

}


public static void main(String array[ ]){
SubClasse referencia = new SubClasse();
System.out.println(referencia.up());



}
}



Sobrescrita de Métodos:


Simplesmente uma SubClasse que troca a implementação de um método da SuperClasse, Lembrando que a assinatura do método deve ser a mesma(Isso inclui Também Mesmo argumentos em Ordem, Tipo e Quantidade).
Então basicamente para um método ser considerado Sobrescrito deve ter mesma Assinatura e diferentes Implementações.

public class Funcionario{


public void metodo(int x, double y){


}

}

public class Gerente extends Funcionario{


public void metodo(
int x, double y){
int x = 0; // Mesma assinatura de metodo, troca de implementação

}


}




Clique na imagem para ampliar


A classe Gerente tem por Herança o - metodo() - Porem nesse caso o método herdado é sobrescrito na classe, VEJA que a implementação de metodo() na Classe Funcionário é diferente da implementação de metodo() na Classe Gerente.



O método Sobrescrito não pode ter menos acessibilidade Vejamos:

public class Funcionario{


public void metodo(int x, double y){


}

}

public class Gerente extends Funcionario{


private void metodo(
int x, double y){
int x = 0; // Mesma assinatura de metodo, troca de implementação

}


}


Erro de Compilação, O modificador de acesso do Método Sobrescrito é menos acessível doque a do método Original, em
Funcionario temos:
public void metodo(int x, double y) - > Método da SuperClasse


EM Gerente
temos a assinatura:
private void metodo(int x, double y) - > Método Sobrescrito



ERRO DE COMPILAÇÃO



É hora da revisão:




- Quando você declara um método, você cria a assinatura dele

- O bloco de código de um método é considerado a implementação dele

- Overload de método são caracterizados por métodos de mesma assinatura porem diferentes argumentos em tipo, ordem ou quantidade.

- Método Sobrecarregados se tiverem a mesma assinatura e diferentes argumentos em tipo,ordem ou quantidade podem ter tipo de retorno diferente

- Podemos ter Overload de Construtores, que diz basicamente:
Várias maneiras de se construir um Objeto

- O this
é usado para:
*Resolve Ambiguidade
*Passar o objeto atual como Parametro
*Invocar um construtor da mesma classe

- A palavra chave this em um construtor deve estar na primeira linha do construtor. Pode haver código depois de this mais não antes

- Se você usar this em um construtor para invocar outro, deve passar parametros normais ao construtor invocado

- Construtores não são herdados

- Para invocar o construtor da SuperClasse use a keyword super()

- super() deve estar na primeira linha do construtor da SubClasse

- super sem paranteses te da acesso a membros da SuperClasse e com parenteses ( ), te da acesso ao construtor da SuperClasse

- Para ter Sobrescrita de um método apenas deixe a Mesma assinatura e troque a Implementação do método

- Métodos Sobrescritos devem ter mesma assinatura que o método original(isso inclui mesmos Argumentos em ordem,tipo e quantidade de argumentos) além do método sobrescrito não pode ter um modificador de acesso menos acessivel doque o método original.

Nenhum comentário:

Postar um comentário