Herança em Java || Duvida sobre classe filha e mãe

Se criar uma classe chamada Animal e criar uma classe chamada Mamifero que herda Animal e depois criar uma classe Cachorro que herda Mamifero, a classe Mamifero sera Mãe da classe Cachoro? O que ela sera?

Me espliquem como que fica essa esquemitizaçao de classe mãe e filha (superclass e subclass) em Java?

Tanto Animal quanto Mamífero serão super classes de Cachorro.

A classe mais próxima dela, no caso Mamífero, será considerada super classe direta e poderá ser acessada usando a palavra chave super.

Da mesma forma, Animal é super classe direta de Mamífero.

A super classe direta de Animal é Object. E Object não tem super classe.

2 curtidas

E se fosse para acessar a classe Animal atravez da Cachorro. Tem como?

Um Cachorro é um Animal, então sua instância de Cachorro, é uma instância de Animal.

1 curtida

Considere o seguinte código:

class Animal {
    void coisaQueQualquerAnimalFaz() { /* ... */ }
}

class Mamifero extends Animal {
    void coisaQueSoMamiferoFaz() { /* ... */ }
}

class Cachorro extends Mamifero {
    void coisaQueSoCachorroFaz() { /* ... */ }
}

class Programa {
    public static void main(String... args) {
        Animal x = new Cachorro();

        x.coisaQueQualquerAnimalFaz();
        x.coisaQueSoMamiferoFaz();
        x.coisaQueSoCachorroFaz();
    }
}

Logo, sim, posso acessar qualquer método ou atributo das super classes de Cachorro, sejam elas super classes diretas (que é o caso de Mamifero) ou indiretas (que é o caso de Animal), desde que não sejam privados.

Agora pode ser que fique uma questão: Qual a utilidade disso?

Imagine que você vai desenvolver um programa para gerenciar um pet shop. Uma das funções deste programa é cadastrar animais.

class Cachorro {
    String nome;
    int idade;
}

class PetShop {
    void cadastrar(Cachorro x) { /* ... */ }
}

No trecho acima, seu pet shop só poderia cadastrar cachorros, mas e se aparecesse um cliente com um gato ou um passáro?

class Animal {
    String nome;
    int idade;
}

class Cachorro extends Animal { /* ... */ }

class Gato extends Animal { /* ... */ }

class Passaro extends Animal { /* ... */ }

class PetShop {
    void cadastrar(Animal x) { /* ... */ }
}

Da forma como demonstrei acima, nosso pet shop agora é capaz de aceitar qualquer animal; poderiámos fazer isso:

PetShop meuPetShop = new PetShop();

Cachorro a = new Cachorro();
a.nome = "Rex";
a.idade = 2;

Gato b = new Gato();
b.nome = "Tom";
b.idade = 3;

// Para instanciar um Passaro, não preciso criar uma variável do tipo Passaro
// Posso usar o tipo Animal. Isto serve para qualquer sub classe de Animal
Animal c = new Passaro();
c.nome = "Piu Piu";
c.idade = 1;

meuPetShop.cadastrar( a );
meuPetShop.cadastrar( b );
meuPetShop.cadastrar( c );

Bons estudos!

Apenas complementando o exemplo postado

class Animal {
    void coisaQueQualquerAnimalFaz() { /* ... */ }
}

class Mamifero extends Animal {
    void coisaQueSoMamiferoFaz() { /* ... */ }
}

class Cachorro extends Mamifero {
    void coisaQueSoCachorroFaz() { /* ... */ }
}

class Programa {
    public static void main(String... args) {
        Animal x = new Cachorro();

        // objeto x foi declarado como Animal, logo, o método abaixo é invocado sem problemas
        x.coisaQueQualquerAnimalFaz();

        // objeto x foi declarado como Animal, logo, o método abaixo vai causar erro
        // pois a classe Animal não possui este método
        x.coisaQueSoMamiferoFaz();

        // objeto x foi declarado como Animal, logo, o método abaixo vai causar erro
        // pois a classe Animal não possui este método
        x.coisaQueSoCachorroFaz();
    }
}
1 curtida

Ah, não acredito que deixei passar isso! Valeu.

@Adriley_Samuel, é como o @staroski corrigiu.

Sua pergunta foi se era possivel acessar a classe Animal através de Cachorro e isso sim daria.

class Programa {
    public static void main(String... args) {
        Cachorro x = new Cachorro(); // o tipo de x deve ser Cachorro

        x.coisaQueQualquerAnimalFaz(); // Cachorro também é um Animal
        x.coisaQueSoMamiferoFaz();     // Cachorro também é um Mamifero
        x.coisaQueSoCachorroFaz();     // Cachorro também é... bem, Cachorro
    }
}

A dica aqui é: teste tudo que for dito pra vc e sempre questione mais.

Desculpa qualquer coisa.

1 curtida

Acessar tem como sim!
Mas o tipo da variável determina os métodos que vc pode acessar.
Nesse situação que vc colocou, mesmo a instancia sendo de cachorro vc só conseguiria chamar os métodos da classe animal. Exemplo: Metodos da Classe Animal : comer() e reproduzir(). Metodos da classe Cachorro : latir() e fingirDeMorto().

Animal animal = new Cachorro();

nessa variavel vc so conseguiria chamar os metodos comer() e reproduzir().

Não li a resposta dos colegas a cima, desculapa se ficar repetitivo -_-

Só dando meus dois centavos, quando você declarar

Animal cao = new Cachorro();

Seu objeto é do tipo Animal, mas possui referência de Cachorro, logo, se vc fizer um cast do obj cao pra classe Cachorro, os métodos de Mamifero e Cachorro passam a ser disponíveis.

((Cachorro)cao).coisaQueSoMamiferoFaz()
((Cachorro)cao).coisaQueSoCachorro()

Isso funciona pq Cachorro IS-A Mamifero IS-A Animal.

Já a declaração abaixo não compilaria, pois a relação entre as classes não atenderia o conceito de Animal IS-A Cachorro

Cachorro cao = new Animal();

2 curtidas

Tudo bem. Valeu :slight_smile: