GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Mecanismo da Herança


#1

Olá a todos no fórum, estava lendo o livro Thinking in Java, e parei nesta frase, que fale sobre herança

Segundo esta explicação pelo que eu entendi a cada vez que criarmos um Objeto que herde de uma outra classe, na verdade criamos dois Objetos, uma da classe filha que é acessado com this, e um da mãe, que é acessado com super, mas que fica escondido dentra da classe filha.
Então posso dizer que quando crio um objeto do tipo ContaCorrente que extends de Conta, na verdade criei três objetos:

Um objeto do tipo ContaCorrente que "dentro" dele terá um objeto da classe Conta, e que dentro de Conta terá um objeto da classe Object !!

Ao meu modo de ver dependendo da hierarquia da herança um objeto então poderia ser "enorme", é isto mesmo ou estou interpretando as coisas erradas.

Obrigado!!


#2

Não se preocupe com o "tamanho" do objeto final na memória. Na prática ele cresce muito pouco.


#3

Vinícius mas o que acontece realmente na memória é isto mesmo que descrevi??

Se tenho uma hierarquia herança deste jeito:

ContaCorrente extends Conta
Conta extends Object

Através de ContaCorrente, eu consigo acessar todos os métodos de Object, então na verdade estou acessando a referência da Conta que dentro dela tem a referência a Object???

Att


#4

Se vc ficar pensando nisso, vc vai pirar... mas é assim mesmo...
Mas fica tranquilo que, diferente do .NET, o GC (PT ou EN) do Java funciona muito bem!!!


#5

Eh verdade. Kra o que eu acho mais complicado de entender na Java é a questão de Herança. Quando acho que entendi, eu leio algo que me contradiz totalmente!!

Att


#6

hehehe Herança as vezes da um nó mesmo....

mais você está no caminho certo, conteste tudo que achar estranho...


#7

Bom... vou descrever o que geralmente acontece. Há pequenas variações de linguagem para linguagem, mas o mecanismo básico, a grosso modo, é o seguinte:

Para cada classe que você cria, há uma estrutura criada descrevendo o nome da classe, o endereço de cada método e os tipos de atributos que os objetos dessa classe que forem instanciados devem ter. É muito similar ao que podemos obter por reflexão na classe "class", mas é claro que é um formato em baixo nível muito menos trabalho e mais compacto.

Quando uma subclasse é criada, uma nova estrutura aparece, descrevendo essa subclasse. Existem duas abordagens que são usadas aqui, não sei exatamente qual é a do java, mas creio que seja a segunda.

  1. A subclasse pode ter um ponteiro para a classe pai, e uma cópia apenas dos métodos que sofrem polimorfismo (no caso do C++, isso é explicitamente dito através da palavra chave virtual).

  2. A subclasse pode ter uma cópia da estrutura do pai, e também o ponteiro para a superclasse, para que sejamos capazes de identificar a hierarquia de classes. Essa me parece ser a abordagem do java, já que todos os métodos são virtuais.

Estamos falando de classes e estruturas que descrevem classes.

Cada objeto criado, irá usar a estrutura de sua subclasse específica apenas para criar os seus atributos, nesse caso, sem repetição dos ponteiros de método. Haverá apenas um ponteiro para o descritor de sua classe específica, e não uma cópia de toda estrutura, como vc provavelmente pensou.

Quanto ocupa uma estrutura que descreve uma classe? Alguns bytes. Uma classe muito grande pode chegar a alguns kb. Ainda sim, essas estruturas são únicas (no caso do Java, únicas por classloader) e não devem ocupar muita memória. Por isso, volto a repetir, não faça disso uma preocupação. Acho até meio que perda de tempo entrar em detalhes como esse... a menos que você vá desenvolver software para algum microcontrolador ou hardware limitado.


#8

Vinícius obrigado pelas respostas, eu não estou me preocupando com isto, só estou querendo entender o mecanismo da herança.

Você quis dizer subclasse mesmo ou superclasse, neste caso superclasse não?

Eu so estou tentando entender ,como no exemplo que dei da ContaCorrente extends Conta e Conta Extends Object.
Então quando eu tentar acessar um método de Object, na verdade eu estou passando primeiro pelo Objeto de Conta, e depois através da referencia de Conta dando um super pra acessar Object, é isto mesmo??

Sem querer ser chato mas já sendo , só estou tentando entender o mecanismo ,pra não ser surpreendido por uma besteira na hora de implementar entende?

Obrigado!


#9

Na prática vc não precisa entender mecanismo interno para usar herança.

Eu quis dizer subclasse mesmo. O objeto tem um ponteiro para a classe mais específica dele. E, na construção, ele usa esse ponteiro para criar todos os seus métodos e atributos. É claro que para isso ele terá que navegar pela superclasse. Mas a estrutura que define a sua subclasse tem um ponteiro para a superclasse, lembra?

Mas isso tudo é feito de forma totalmente transparente, pelo Java. Você não precisa se preocupar em como trabalha o mecanismo em si, só com o funcionamento resultante.

Quando você faz uma herança, o que o java te permite acessar é:
1. Os métodos e atributos de sua classe;
2. Os métodos e atributos da classe mãe;
3. Os método mais específico redefinido nas classes avó. Os atributos também, desde que não haja shadowing;

Exemplo:

public class Conta extends Object {
    public void hashCode() {
          return numeroDaConta && 0xDEADCODE;
    }
    public String getName() {
     return "Conta padrão";
}
}
public class ContaPessoaFisica extends Conta 
{
    public void equals(Object o) {
        return super.equals(o);
    }
    public void hashCode() {
     return super.hashCode() + 2;
}

public String getName() {
     return "Pessoa física";
}

public String getExtendedName() {
     return "Conta de " +  getName();
}

Da classe ContaPessoaFisica conseguimos:
1. Acessar o método getName() da classe Conta, através da chamada super.getName();
2. Acessar o getName() da nossa própria classe, como em getExtendedName();
3. Acessar o método equals da classe Object, através de super.equals (última redefinição de equals);
4. Acessar o método hashCode da classe Conta (última redefinição de hashCode) , através de super.hashCode(). Note que não conseguiriamos acessar o hashCode() da classe Object. Não é possível fazer: super.super.hashCode();

Também é interessante notar que poderíamos chamar super.hashCode() em qualquer método, não só na redefinição de hashCode(). Ou seja, a qualquer momento, podemos acessar os métodos da classe mãe, mesmo tendo redefinido esse método na nossa própria classe Conta.


#10

Viny, valeu mesmo kraaa, agora sim deu pra entender legal!!

Então enquanto eu não redefinir o método ele sempre executa o da mãe! Porque dentro dele tem um super, mais a partir do momento que eu redefino na classe filha, eu só consigo ter acesso ao método da classe filha e do pai, e não mais do avô.

Eh que sou meio curioso e gosto de entender realmente como as coisa funcionam, desculpa se te enchi muito a paciência, e obrigado.

Att


#11