Polimorfismo

olá colegas gostaria de uma explicação legal para a seguinte situação:

Classe Pai:

public class Veiculo {

    private String modelo;
    private String cor;
    private int ano;
    
    public Veiculo() {
        System.out.println("Criado um veículo");
    }

  //getters e setters   

}

Classe Filha

public class Carro extends Veiculo{

    private String motor;
   //getters e setters
    
   
    public Carro() {        
         System.out.println("criado um carro....");
    }

    
    public void passaMarcha(){
        System.out.println("passei a marcha");
    }

}

classe teste

public class Teste {    
    public static void main(String[] args) {        
    Veiculo c1 = new Carro();

      c1.setCor("verde"); //ok da classe veiculo
      //passa pelo construtor de carro
     //mas não acessa os atributos e métodos de carro.

    }

}

Gostaria que me ajudasse a esclarecer isto
qual alguma vantagem de uma chamada do tipo Veiculo c1 = new Carro(), ao inves do objeto carro direto?

ps. não estou discutindo se é melhor usar interfaça, herança ou polimorfismo, esotu tentando construir uma explicação mais robusta para uma aula…

obrigado

sempre que vc instancia um objeto que possua um pai, o construtor dele é invocado vc chamando super() ou não.
Por isso ele diz que foi criado um veiculo. ele cria a classe veiculo dentro da classe carro.

a vantagem de se usar Veiculo v = new Carro();

e que se seu veiculo mudar para uma caminhão, vc altera uma linha de código (Veiculo v = new Caminhao();), não um sistema inteiro. Quando a aplicação é pequena não se nota isso, mas em uma aplicação grande faz toda a diferença.

[]'s

certo, mas qual a explicação do objeto do tipo :

Veiculo c1 = new Carro(), não acessar os métodos de carro por exemplo?

Veiculo e Carro, Carro extends Veiculo, assim sendo Carro é um Veiculo com mais métodos. Com o uso da herança você consegue usar todos os métodos de veículos, se a classe Carro (filha) tiver métodos novos você conseguirar usar também, agora se você fizer Veiculo p1 = new Carro(); Você só poderá usar os métodos que todos os veículos tem, os específicos de carro não, ou seja, você só vai poder chamar métodos e atributos de objetos Veiculo num objeto Carro.

Isto está relacionado com as possíbilidades que os níveis de abstração lhe oferece.
Levando em consideração o seu exemplo, fica muito mais fácil e prático vc utilizar a instancia da classe Veiculo se vc for lidar com o dado ano, modelo ou cor; seu código irá ficar menor e simples de entender porque vc estará atuando no nível de abstração que trata justamente os dados que lhe interessa. Isso muitas vezes causa confusão porque se trata muitas vezes de estratégia, ou seja, as vezes vc pode utilizar um nível de abstração menos adequado e ainda assim conseguir atingir o seu objetivo e em outros momentos o nível de abstração talvez não faça muita diferença. O maior benefício é a qualidade do código resultante.

flws

dependendo do código vc pode verificar se veiculo é uma instancia de carro para usar os metodos de carro

if( v instanceof Carrro){
   Carro c = (Carro) v;
   //Agora pode usar a vontade os metodos do carro
}

[]'s