quarta-feira, 9 de setembro de 2009

Polimorfismo,cast Objetos,instanceof

Sumário: Polimorfismo,Sobrescrita e Polimorfismo,Argumentos e Polimorfismo,cast de Objetos,instanceof

Objetos tem apenas uma forma aquela que lhe é dada quando ele é construído porem uma variável é polimórfica ou seja ela faz referência para diferentes objetos.
Relembrando:



Como se declara uma variável de referência?





Clique na imagem para ampliar



Quando eu crio um objeto oque realmente acontece?


Acontece a subida no topo da hierarquia do objeto, obtendo - se um objeto que tem tanto membros(Métodos, Atributos) próprios quanto de todas as SuperClass da Hierarquia.
Vejamos:





Clique na imagem para ampliar
, Lembrando que Implicitamente escrito ou explicitamente Toda Classe que não tenha um SuperClasse explicitamente escrito tem java.lang.object Implicitamente ou Explicitamente escrito como SuperClasse.


Sabemos que se criarmos um objeto do tipo
Chefe, ele terá todos os membros(Métodos e Atributos que todas as Hierarquias acima).


Vejamos:




new Chefe();



Vamos obter isso:





Clique na imagem para ampliar
Ja deu para perceber que todo objeto Chefe tem:
Tudo que é de direito ao cargo, no caso
carroEmpresa
Chefe também
tem tudo que encarregado tem no caso bonusSalarial e supervisionar()
Chefe também
tem tudo que Funcionário tem no caso nome, salario e trabalhar()
Chefe também
tem tudo que java.lang.Object tem Sendo assim vou abreviar para ficar mais facil o entendimento:








Outro exemplo:



Se Criar-mos um objeto Funcionario, Resumidamente teremos:


Lembre-se que todo funcionário tem:

Oque é de direito ao cargo dele no caso : nome, salario e trabalhar()

E todo objeto Funcionário tem tudo que java.lang.Object tem




Relação variável de referência e Objeto:


É aqui realmente que se encontra o Polimorfismo, de acordo com a palavra em si:
Polimorfismo = Muitas formas

De acordo com a variável de referência você poderá acessar somente OQUE FAZ PARTE DAQUELE TIPO DE OBJETO VEJAMOS:

Como Chefe é um Encarregado, ou seja é uma SubClasse da Classe Encarregado, Então isso é possível:




Clique na imagem para ampliar





Oque acabamos de fazer?


Aqui temos um objeto do tipo Chefe porem a variável aponta para o objeto do tipo Encarregado, OU SEJA ela somente pode usar tudo que um Encarregado tem...
Um chefe é um Encarregado
Porem um Encarregado não é um chefe

Vejamos:



Clique na imagem para ampliar
Se você tentar acessar:

identificador.carroEmpresa = true; Dará Erro de Compilação, Pois A variável de referência é do tipo Encarregado, E ENCARREGADO não tem carro da Empresa.

Se você tentar acessar:

identificador.trabalhar(); Compilará Normalmente, Pois o método trabalhar é de Funcionário e a variavel de referência Aponta para o Encarregado do Objeto, e Encarregado é um Funcionário.

Por isso chegamos a conclusão de:
Um objeto só tem uma forma porem a variável de referência pode apontar para qualquer forma dele.


Sobrescrita e Polimorfismo:

Muita atenção em Sobrescrita e Polimorfismo,

Vejamos o exemplo:

public class Funcionario{

public void metodo(){
System.out.println("Funcionario");

}

}

public class Gerente extends Funcionario{

public void metodo(){
System.out.println("Gerente");

}


}


public class TestClass{

public static void main(String array [ ]){

Funcionario funcionario = new Funcionario();
funcionario.metodo();


Gerente gerente = new Gerente();
gerente.metodo();



}

}




Clique na imagem para ampliar




Em
funcionario.metodo(); Aparecerá:
Funcionario


Em
gerente.metodo(); Aparecerá:
Gerente

Podemos ver dessa forma também:




Clique na imagem para ampliar





Porem isso não acontece aqui:


Temos uma diferença seria quando existe Sobrescrita de método e Polimorfismo


public class Funcionario{

public void metodo(){
System.out.println("Funcionario");

}

}

public class Gerente extends Funcionario{

public void metodo(){
System.out.println("Gerente");

}


}

public class TestClass{

public static void main(String array [ ]){

Funcionario funcionario = new Gerente();
funcionario.metodo();




}

}


Neste exemplo oque teremos na saída Padrão é:

Gerente

POR CAUSA DA SOBRESCRITA QUE ISSO ACONTECE

Em métodos sobrescritos na verdade obtém-se o comportamente associado ao objeto em tempo de EXECUÇÃO ou seja, invocamos o método do objeto gerente cujo sobrescreve o método da SuperClasse dele ou seja Funcionario.

PORTANTO CUIDADO COM INVOCAÇÃO DE MÉTODOS SOBRESCRITOS.



Argumentos e Polimorfismo:


Você pode ter um Argumento de um tipo que seja uma SuperClasse e pode receber qualquer parâmetro que seja uma SubClasse dessa SuperClasse que esta como argumento.

Vejamos:




Clique na imagem para ampliar


Vejamos em sintax java:



public class Funcionario{

public void
metodo(Object argumento){

}


}


public class
Encarregado extends Funcionario{

}


public class
Chefe extends Encarregado{

}


public class
ClassTest{


public static void main(String array[ ]){


Chefe chefe = new Chefe();


Encarregado encarregado = new Encarregado();


Funcionario funcionario = new Funcionario();


chefe.metodo(encarregado);

chefe.metodo(funcionario);


encarregado.metodo(chefe);

encarregado.metodo(funcionario);


funcionario.metodo(chefe);

funcionario.metodo(encarregado);

}


}



Quando fiz isso:



Chefe chefe = new Chefe();


Encarregado encarregado = new Encarregado();


Funcionario funcionario = new Funcionario();

Obtive:





Clique na imagem para ampliar



POREM CUIDADO:


Dentro do Frame
metodo(Object argumento) eu estou me referênciando ao Objeto como se fosse um Object, oque implica em:

Nesse exemplo:

funcionario.metodo(chefe);

Eu obtive:




Clique na imagem para ampliar

Oque Significa que eu SO TENHO ACESSO A PARTE java.lang.Object DO MEU OBJETO, ou seja desse Jeito eu não posso nem invocar:

argumento.metodo
(Parametros); // Isso da erro de Compilação ja que argumento aponta PARA O TIPO java.lang.Object do Objeto.


EM invocações:


chefe.metodo(encarregado);

chefe.metodo(funcionario);


encarregado.metodo(chefe);

encarregado.metodo(funcionario);


funcionario.metodo(chefe);

funcionario.metodo(encarregado);



Simplesmente passei o endereço de memória referente ao objeto, nesse exemplo seria assim:

encarregado.metodo(funcionario);
encarregado.metodo(0xA3);

chefe.metodo(encarregado);
chefe.metodo(0xA2);

funcionario.metodo(chefe);
funcionario.metodo(0xA1);


Cast de Objetos:

Em algunas casos recebo como parametro uma referência de um objeto de uma SubClasse e como argumentos tenho uma classe que é SuperClasse dela, porem quero obter as funcionabilidades específicas da SubClasse, então posso fazer cast de OBJETOS.


Vejamos o exemplo:
Lembrando que toda classe que não é declarado explicitamente nenhuma SuperClass tem java.lang.Object como SuperClasse Primária.




Clique na imagem para ampliar



public class Funcionario{

public void metodo(Object argumento){
Encarregado cast = (Encarregado) argumento; cast.exclusivo();
}

}

public class Encarregado extends Funcionario{

public void exclusivo(){
System.out.println("Metodo Exclusivo");
}

}


public class TestClass{

public static void main(String array[ ]){
Encarregado referencia = new Encarregado();
referencia.metodo(referencia);

}
}


Vejamos oque acontece quando o
referencia.metodo(referencia); sobe o Frame .metodo(referencia) na Stack de main:

Ao invocar
referencia.metodo(referencia) temos dentro do Frame: public void metodo(Object argumento):





Clique na imagem para ampliar
Nessa instrução:


Encarregado cast = (Encarregado) argumento;

Temos agora:


Clique na imagem para ampliar, Sendo a posição 0 da Local Variable a referência a Constant Pool, posição 1 argumento , posição 2 cast.

Perceba na imagem acima,
que a variavel argumento tem acesso somente a parte java.lang.Object do nosso Objeto encarregado ja a variavel cast tem acesso a Parte Encarregado do nosso Objeto, ou seja a variavel cast TEM ACESSO A TUDO DO OBJETO, por isso é possível invocar
exclusivo().


Operador instanceof:

Simplismente uma maneira de ter certeza que o cast do Objeto é aceitável, vamos supor:



Clique na imagem para ampliar



public class Funcionario{

public void metodo(Object variavelArgumento){

Encarregado variavelCast = (Encarregado) variavelArgumento;
variavelCast.
exclusivoEncarregado();

}
}

public class Encarregado extends Funcionario{

public void exclusivoEncarregado(){


}
}

public class ClasseSolta{

}

public class ClassTest{


public static void main(String array[]){

Encarregado d = new Encarregado();
ClasseSolta variavelSolta = new ClasseSolta();

d.metodo(variavelSolta);

}
}


Isso gera uma Exception. Vejamos:

Dentro da
ClassTest temos o método main nele , instanciamos um Objeto do tipo ClasseSolta, como ClasseSolta é uma SubClasse de java.lang.Object Obtemos nessa instrução, ClasseSolta variavelSolta = new ClasseSolta();// Ou seja na instanciação do Objeto

isso:




Quando invocamos:

d.metodo(variavelSolta);

Sobe-se o frame do método de assinatura:
public void metodo(Object variavelArgumento)



Clique na imagem para ampliar

Então verfica-se o seguinte,
variavelSolta é do tipo Object?

Sim variavelSolta tem uma referência a um objeto do tipo Object dentro dela também ou seja:




Seguindo Instruções:

Encarregado variavelCast = (Encarregado) variavelArgumento;
Da para a
variavelCast apontar para a parte Encarregado do objeto ao qual variavelArgumento tem uma referência?





Não, variavelArgumento é do tipo ClasseSolta que é uma SubClasse de java.lang.Object logo não tem um objeto do tipo Encarregado. Ate poderiamos fazer um cast para ClasseSolta.


Veja como o compilador tentar ver:




Clique na imagem para ampliar,- Houve a tentativa de fazer cast para que a
variavelCast aponte para a parte Encarregado do objeto porem o objeto é do tipo java.lang.Object e ClasseSolta, como vou achar algo que ela não tem?



Agora se fizer isso:

public class Funcionario{

public void metodo(Object variavelArgumento){

if(variavelArgumento instanceof Funcionario){
Encarregado variavelCast = (Encarregado) variavelArgumento;
variavelCast.exclusivoFuncionario();

}


}

}

public class Encarregado extends Funcionario{

public void exclusivoFuncionario(){

}

}

public class
ClasseSolta{

}

public class
ClassTest{

public static void main(String array[]){

Encarregado d = new Encarregado();


ClasseSolta variavelSolta = new ClasseSolta();

d.metodo(variavelSolta);


}


}

Reparte que em
ClassTest invocamos:
d.metodo(variavelSolta);

Sobe-se o frame do metodo de assinatura:
public void metodo(Object variavelArgumento)

Faz-se a verificação, o objeto
ClasseSolta a qual a variavel de referencia variavelSolta
aponta é do tipo Object também? SIM!


Então entra-se na lógica do método:

if(variavelArgumento instanceof Funcionario)

variavelArgumento aponta para um objeto do tipo ClasseSolta, essa ClasseSolta é uma SubClasse de Funcionario?
A resposta é não, porem existe uma lógica de tratamento então simplesmente o programa não executa o bloco de código do if, porem NÃO DA EXCEPTION.


Dicas sobre cast:

1 - Uma "Promoção" de objetos é permitida sem nenhum operador de cast,Sendo Funcionario a SuperClasse Direta de Encarregado, vejamos:


public class Funcionario{

}



public class Encarregado extends Funcionario{

}



public class TestClass{

public static void main(String array[ ]){

Funcionario referencia = new Encarregado();

}
}


2 - Para asseguar que não haja exception, use instanceof antes de cast



- Muito CUIDADO AO TER HERANÇA POLIMORFISMO E SOBRESCRITA DE MÉTODOS.


CYA DUDES!!!

Construtores e Herança em java

A construção de objetos é feita subindo-se a hierarquia da Classe:

Passo a passo para construção de um objeto em Runtime:

1 - Memória é alocada para o objeto
2 - Variaveis de Instancia recebem valor Default
3 - Verifica-se se Parametros e argumentos tem mesmo tipo,ordem,quantidade
4 - Tem this explicito? Se tiver executa this, isso se this for chamada a outro construtor
5 - Chamar super(), implicito ou explicito(De qualquer modo ele sempre é chamado)
6 - Executa-se os inicializados das variáveis de instancia(Explicitos)
7 - Executa - se o bloco_de_codigo do construtor

Considerações:
- O passo 1 e passo 2 somente são feitos uma vez
- O passo 4 só é considerado se tiver uma CHAMADA this sozinha a outro construtor.
- O passo 5 sempre é feito, independente se explicitamente ou implicitamente, só não é feito em java.lang.Object porque ele ja é TOPO da hierarquia.
- O passo 6 é considerado SOMENTE quando você inicializa a variavel quando declara
Exemplo:


public int variable = 20;

Se a inicialização for feita dentro do construtor é considerado passo 7:

public int variable;

public Classe(){
variable = 20;

}

Oque acontece se houver uma chamada a this?

Se houver uma chamada explicita a this para outro construtor, entra outro construtor e incia-se do numero 3 em diante.

Oque é aload_0?
aload_0 é o this, ou seja uma referência a Constant Pool, que depois será Runtime Constant Pool e consequentemente com dynamic Linking a Heap


Posso ter this e super no mesmo construtor?

Sabemos que this ou super devem esta na primeira linha do construtor, logo se temos this não temos super e se temos super não temos this, Pois ambos tem que estar na primeira linha do construtor.



Vejamos um exemplo:




public class Pessoa{

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


public 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");


}

}

Em Sintaxe bytecode temos:


Compiled from "Pessoa.java"
public class Pessoa extends java.lang.Object{
public Pessoa(java.lang.String, java.lang.String, int);
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."init>:()V
4: aload_0
5: aload_1
6: putfield #2; //Field name:Ljava/lang/String;
9: aload_0
10: aload_2
11: putfield #3; //Field endereco:Ljava/lang/String;
14: aload_0
15: iload_3
16: putfield #4; //Field numeroCasa:I
19: return

public Pessoa(java.lang.String, java.lang.String);
Code:
0: aload_0
1: aload_1
2: aload_2
3: iconst_0
4: invokespecial #5; //Method "":(Ljava/lang/String;Ljava/lang/String;I)V
7: return

public static void main(java.lang.String[]);
Code:
0: new #6; //class Pessoa
3: dup
4: ldc #7; //String Maria
6: ldc #8; //String Rua das flores
8: invokespecial #9; //Method "":(Ljava/lang/String;Ljava/lang/String;)V
11: astore_1
12: return

}





No frame main, podemos verificar alguns passos:


Code:
0: new #6; //class Pessoa
3: dup
4: ldc #7; //String Maria
6: ldc #8; //String Rua das flores
8: invokespecial #9; //Method "init>":(Ljava/lang/String;Ljava/lang/String;)V
11: astore_1
12: return


Passo a passo:


1 - Memória é alocada para o objeto
2 - Variaveis de Instancia recebem valor Default

Podemos considerar instruções iguais em:
0: new #6; //class Pessoa
3: dup


Code:
0: new #6; //class Pessoa
3: dup
4: ldc #7; //String Maria
6: ldc #8; //String Rua das flores
8: invokespecial #9; //Method "init>":(Ljava/lang/String;Ljava/lang/String;)V

Na instrução 8, ele invoca o construtor da propria Classe e passa como parametros oque esta na Operand stack logo estamos no Construtor da classe.
Isso indica que é da própria classe: porque antes de não tem especificação de classe nenhuma //Method "init>": Na verdade o init seria com <>...init estaria entre os <>...é que o blog da problemas com isso.

Vamos para o passo 3 do passo a passo:

3 - Verifica-se se Parametros e argumentos tem mesmo tipo,ordem,quantidade

Logo após feita e confirma o passo 3, estamos dentro do construtor da classe Pessoa

public Pessoa(java.lang.String, java.lang.String);
Code:
0: aload_0
1: aload_1
2: aload_2
3: iconst_0
4: invokespecial #5; //Method "init>":(Ljava/lang/String;Ljava/lang/String;I)V
7: return

Nesse construtor na instrução:
4: invokespecial #5; //Method "init>":(Ljava/lang/String;Ljava/lang/String;I)V

Percebemos que estamos no passo 4 do passo a passo
4 - Tem this explicito? Se tiver executa this, isso se this for chamada a outro construtor
Aqui tem this explicito, logo vamos pra o outro construtor da classe:(Perceba que o construtor invocou esse outro construtor, veja que eles tem Argumentos diferentes)

public Pessoa(java.lang.String, java.lang.String, int);
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: aload_0
5: aload_1
6: putfield #2; //Field name:Ljava/lang/String;
9: aload_0
10: aload_2
11: putfield #3; //Field endereco:Ljava/lang/String;
14: aload_0
15: iload_3
16: putfield #4; //Field numeroCasa:I
19: return



Repete-se o processo:

3 - Verifica-se se Parametros e argumentos tem mesmo tipo,ordem,quantidade
4 - Tem this explicito? Se tiver executa this, isso se this for chamada a outro construtor - Nesse caso não tem chamada a this dentro do construtor

5 - Chamar super(), implicito ou explicito(De qualquer modo ele sempre é chamado), Podemos ver isso na instrução:
1: invokespecial #1; //Method java/lang/Object.init>:()V
nessa linha de codigo, nota-se que tem uma invocação na classe:

java/lang/Object
e é o construtor indicado pelo: "
init>":()V
Ou seja invoca-se o construtor da classe java.lang.Object, A superClasse de toda classe em java.Na verdade a instrução
init> esta faltando um <....é que o blog da problema pois trabalha como edição em html também...mais na verdade seria algo assim...< ....init> com o <>



Na classe java.lang.Object temos o teste novamente:

3 - Verifica-se se Parametros e argumentos tem mesmo tipo,ordem,quantidade(Não Tem, pois o construtor não tem argumentos e logo não passamos parametros!!!)
4 - Tem this explicito? Se tiver executa this, isso se this for chamada a outro construtor(Não Tem!!!)
5 - Chamar super(), implicito ou explicito(De qualquer modo ele sempre é chamado)(java.lang.Object é root da hierarquia logo , não temos SuperClass)
6 - Executa-se os inicializados das variáveis de instancia(Explicitos)(Não Tem!!!)
7 - Executa - se o bloco_de_codigo do construtor(Não Tem!!!)



Então voltamos para o construtor da classe Pessoa:

6 - Executa-se os inicializados das variáveis de instancia(Explicitos)
Nesse caso não temos, pois as variaveis de instancia forão declaradas somente e não inicializadas ao declarar

7 - Executa - se o bloco_de_codigo do construtor
this.name= name;
this.endereco = endereco;
this.numeroCasa = numeroCasa;
Terminou-se o bloco de codigo.


Clique na imagem para ampliar



É bom lembrar, que se tivermos "n" classes antes de chegar em java.lang.Object o processo é feito em cada uma das SuperClasses até root,

Vejamos o exemplo:





Clique na imagem para ampliar

Nesse caso se instanciarmos um objeto do tipo Chefe, o passo 1 e 2 só são feitos uma vez e o resto dos passos é feito a cada hierarquia ate java.lang.Object...

Exemplo:


new Chefe();

1 - Memória é alocada para o objeto
2 - Variaveis de Instancia recebem valor Default
3 - Verifica-se se Parametros e argumentos tem mesmo tipo,ordem,quantidade
4 - Tem this explicito? Se tiver executa this, isso se this for chamada a outro construtor - Supondo que não temos this explicito
5 - Chamar super(), implicito ou explicito(De qualquer modo ele sempre é chamado)


Construtor da classe Encarregado pois é super de Chefe:

3 - Verifica-se se Parametros e argumentos tem mesmo tipo,ordem,quantidade
4 - Tem this explicito? Se tiver executa this, isso se this for chamada a outro construtor - Supondo que não temos this explicito
5 - Chamar super(), implicito ou explicito(De qualquer modo ele sempre é chamado)

Construtor da classe Funcionario pois é super de Encarregado:

3 - Verifica-se se Parametros e argumentos tem mesmo tipo,ordem,quantidade
4 - Tem this explicito? Se tiver executa this, isso se this for chamada a outro construtor - Supondo que não temos this explicito
5 - Chamar super(), implicito ou explicito(De qualquer modo ele sempre é chamado)


Construtor da classe java.lang.Object pois é super de Funcionario:

3 - Verifica-se se Parametros e argumentos tem mesmo tipo,ordem,quantidade(Não Tem, Construtor da classe java.lang.Object não requer parametros pois não tem argumentos!!!)
4 - Tem this explicito? Se tiver executa this, isso se this for chamada a outro construtor(Não Tem!!!)
5 - Chamar super(), implicito ou explicito(De qualquer modo ele sempre é chamado)(java.lang.Object é root da hierarquia logo , não temos SuperClass)
6 - Executa-se os inicializados das variáveis de instancia(Explicitos)(Não Tem!!!)
7 - Executa - se o bloco_de_codigo do construtor(Não Tem!!!)

Então agora voltamos para a classe Funcionario:

6 - Executa-se os inicializados das variáveis de instancia(Explicitos)
7 - Executa - se o bloco_de_codigo do construtor

Agora vamos para a classe Encarregado:
6 - Executa-se os inicializados das variáveis de instancia(Explicitos)
7 - Executa - se o bloco_de_codigo do construtor

Agora a classe Chefe:
6 - Executa-se os inicializados das variáveis de instancia(Explicitos)
7 - Executa - se o bloco_de_codigo do construtor



Provando que o passo 5 sempre é executado:

public class Test{



}

Em sintax bytecode temos:

Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."init>":()V
4: return

}

Veja que o construtor da classe é acrescentado pelo compilador, e o mesmo faz uma chamada ao construtor da classe Object:
1: invokespecial #1; //Method java/lang/Object."init>":()V

Bom é isso!!!
Basicamente o construtor vai trabalhando com hierarquia de classes,
CYA DUDES!!!

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.