Quebrando a Cabeça: Modificador de acesso + Método Sobrescrito

Pessoal,

to tentando achar uma razão para esse código funcionar, dêem uma olhada:

package pacote;

public class Animal {

	protected void metodo(){
		System.out.println("metodo animal");
	}
	
}
package outroPacote;

import pacote.Animal;

public class Cavalo extends Animal{
	
	protected void metodo(){
		System.out.println("metodo Cavalo");
	}
	
}
package pacote;

import outroPacote.Cavalo;

public class Teste
{
	public static void main(String[] args){
		Animal a = new Cavalo();
		a.metodo();
	}
}

A saída de dados é: metodo Cavalo.

Dúvida: O método sobrescrito em cavalo, possúi o modificador de Acesso “protected”, ou sejá só deveria ser acessado em subclasses de Cavalo ou no mesmo pacote.
No exemplo acima, a classe Teste não é subclasse de cavalo e nem está no mesmo pacote, porém em tempo de execução, o metodo protected é acessado normalmente.

Alguém sabe justificar?

Obrigado !

Teu problema ta no new Cavalo.

A classe pai nao enxerga o construtor da classe filho, logo esse new esta sendo de forma equivocada.

se vc fizer ao contrario vai funcionar, Cavalo c = new Animal();

nesse caso o metodo q vc chamaria seria a da classe animal, pois o objeto gerado foi da classe animal.

JavaMania,

devo lembrar que o código está compilando e rodando normalmente, a minha dúvida é como o método sobrescrito consegue ser executado com o modificador protected.

OBS: Cavalo c = new Animal(); Não funcionaria, acho que você se confundiu.
Uma referência de Animal pode receber uma instância de Cavalo perfeitamente, pois Cavalo é um Animal (uma vez que: Cavalo extends Animal). Porém uma referência de Cavalo não pode receber uma instancia de Animal, pois Animal pode não ser um Cavalo. Concorda?

Abraço.

Perdão realmente me confundi, obrigado pela correção

:stuck_out_tongue:

qual a saida que esta acontecendo com esse codigo?

O modificador protected é menos “rígido” do que modificador default.

Utilizando default (ou seja, deixando de colocar qualquer modificador) num método, as sub classes somente herdam esse método se estiverem no mesmo pacote. O que não acontece com protected. Mesmo classes de outros pacotes herdam os métodos protected.

Resumindo:

default: restrição a nível de pacote para herança e simples acesso

protected: restrição a nível de pacote para simples acesso

Ola, ataufo

Primeiramente parabens por estar estudando para a certificacao, o que o JavaMania disse realmente esta errado, isso aqui nao existe :
Cavalo c = new Animal();
pois nao vai funcionar, o certo eh o contrario como voce disse, mas vou explicar o que acontece no seu codigo.

A classe Teste nao precisa fazer parte de heranca nenhuma, voce usa ela exatamente como o nome diz “Teste” ,

Entao dentro do main quando voce faz isso :

Animal a = new Cavalo(); a.metodo();

voce esta instanciando, imagina assim eh como se voce pegasse o codigo dessas classes Animal e Cavalo e colocasse tudo dentro do metodo main, entende, entao todo o codigo tanto de Animal quanto de Cavalo passa a estar dentro desse metodo main(ou seja, roda dentro do main) e classe teste serve apenas digamos de “carcaça” (essa foi boa rsrsrs) para o codigo funcionar.

bem ta numa linguagem assim bem leiga, mas faco isso para que voce tente entender o conceito.

espero que eu tenha ajudado ,
se nao posta ai que eu tento explicar denovo rsrsrs.

flw.

package pacote;

import outroPacote.Cavalo;

public class Teste
{
	public static void main(String[] args){
		Animal a = new Cavalo(); //Cavalo é publico logo, vc pode dar new no Cavalo
		a.metodo(); //vc esta envocando o método de Animal que é protected e vc esta no mesmo pacote logo vc pode faze-lo
		// o método envocado é o de Cavalo pq ele foi sobrescrito, e vc não invocou diretamente o de cavalo, pois este vc não teria acesso

		Cavalo c = new Cavalo(); //por exemplo aki vc tem um cavalo
		c.metodo(); //isso aki é impossivel, pois vc estaria incovando o metodo de outro pacote, o qual vc não enxerga
	}
}

espero q de pra entender

rod.atack: perfeito, porém não tem relação com a minha dúvida.

danieldomingues86: entendi o que você quis dizer, porém normalmente o metodo main não teria acesso ao metodo protected.

Lavieri:

[quote] a.metodo(); //vc esta envocando o método de Animal que é protected e vc esta no mesmo pacote logo vc pode faze-lo
// o método envocado é o de Cavalo pq ele foi sobrescrito, e vc não invocou diretamente o de cavalo, pois este vc não teria acesso[/quote]
Concordo, o compilador encherga somente o método de Animal.

Concluo que, em tempo de execução, o java executa o metodo de Animal e verifica se ele foi sobrescrito pela subclasse, caso sim, executa o metodo sobrescrito, ignorando se você possui acesso direto ou não.

Obrigado galera.

O modificador protected pertimite o acesso nos seguintes casos:

  • Pela própria classe;
  • Pelas suas sub-classes;
  • Pelo pacote.

Animal está no pacote “pacote”, portanto, outras classes que pertencem ao pacote “pacote” (como Teste) têm acesso aos métodos protected de Animal.

A classe Cavalo pertence ao pacote “outroPacote”.

Todo Cavalo é um Animal, mas nem todo Animal é um Cavalo.

Assim, a declaração correta é:

Falou!