> For the complete documentation index, see [llms.txt](https://educacion.gitbook.io/programacion/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://educacion.gitbook.io/programacion/ud4-elementos-da-programacion-orientada-a-obxectos/herdanza.md).

# Herdanza

A herdanza é un mecanismo da linguaxe que nos vai a permitir a creación de novas clases a partir de outras xa existentes. De maneira xeneral, imos atopar:

1. **Clases pai ou superclases**, nas que imos a definir atributos é métodos comúns
2. **Clases fillas ou subclases**, que van a herdar (ou redefinir) todas los métodos das clase pai, ademis de poder definir os seus propios métodos.

{% hint style="warning" %}
**Java non admite herdánza múltiple**: Unha clase unicamente pode ter un pai,e pode ter todos os fillos que queira.

A **xerarquía que se define coa herdanza**, pode ter n niveles.
{% endhint %}

Dada a seguinte clase pai:

```java
public class Animal {

    private String nome;

    public Animal(){
        this("");
    }

    public Animal(String nome){
        this.nome=nome;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public void emitirSonido(){
        System.out.println("Fago un sonido xenérico");
    }

    public String describir() {
        return "Soy un animal llamado " + this.nome;
    }
    
}
```

Podemos **extendela en outra clase filla** mediante a palabra reservada **`extends`**<i class="fa-copy">:copy:</i>. No noso caso, a clase Paxaro vai a ter, ademais características de cor da plumaxe e número de dedos.

```java
public class Paxaro extends Animal{

    private String colorPlumas;
    private int numeroDedos;


    public String getColorPlumas() {
        return colorPlumas;
    }

    public void setColorPlumas(String colorPlumas) {
        this.colorPlumas = colorPlumas;
    }

    public int getNumeroDedos() {
        return numeroDedos;
    }

    public void setNumeroDedos(int numeroDedos) {
        this.numeroDedos = numeroDedos;
    }
}
```

Unha vez implementadas as clases, na nosa App poderiamos escribir o seguinte código, que devolvería a seguinte saida:

```java
Paxaro pega = new Paxaro();
pega.setNome("Peggy"); //método da clase Animal
pega.setColorPlumas("Azul,blanco y negro"); //método da clase Paxaro
pega.setNumeroDedos(3); //método da clase Paxaro
System.out.println("Numero de dedos:" + pega.getNumeroDedos()+  
", Color: " + pega.getColorPlumas());
pega.emitirSonido(); //método da clase Animal
System.out.println(pega.describir()); //método da clase Animal
```

Aínda que esta implementación é correcta, ten varios problemas, xa que:

* Necesitaríamos un constructor ou constructores que poda recibir todos os atributos (pai, fillo)
* O método emitirSonido() debe de ter un comportamento especifico para os paxaros
* Ó método describir() está incompleto, xa que únicamente devolve a información propia dos animais, non a información propia dos animais e os paxaros.

## Super

A palabra reservada `this` utilízase para facer referencia a propia clase. De forma análoga, temos **`super` que fai referencia a superclase da clase onde se utiliza**. Esta palabra clave resulta moi útil cando se desexa acceder a membros (atributos e métodos) da clase pai que poidan estar ocultos ou redefinidos na subclase.

`super` permite **chamar un método da superclase** dende unha subclase, aínda que a subclase teña un método co mesmo nome. Isto é **útil cando se redefine un método** na subclase, pero aínda se necesita o comportamento orixinal da superclase.

### Constructores

Para iso dispoñemos do método **`super()`**<i class="fa-copy">:copy:</i>**, que invoca o construtor da superclase**. En caso de estar sobrecargados, podemos variar os seus parámetros de entrada en número e tipo. Unha restrición en ter en conta con `super()`<i class="fa-copy">:copy:</i> **é que ten que ser forzosamente a primeira instrución do constructor**.

```java
public Paxaro(String nome, String colorPlumas, int numDedos){
        super(nome);// chamamos ao new Animal(nome) "interno" do paxaro
        //setteamos os atributos 
        this.colorPlumas=colorPlumas;
        this.numeroDedos=numDedos;
    }
    //Nos seguintes constructores podense facer referencias 
    //aos constructores da propia clase mediante a palabra this, 
    //ou a super e setteando os valores
    public Paxaro(String nome, String colorPlumas){
        this(nome,colorPlumas,0);
    }
    
    public Paxaro(){
        this("","",0);
    }
```

### Redefinición de métodos

En Java, a **redefinición de métodos** (tamén chamada “sobreescritura” ou *overriding*) permite que unha **subclase poida modificar o comportamento dun método herdado da súa superclase**. Isto é útil cando se quere que unha clase derivada teña unha funcionalidade particular que se diferencie da da clase pai.

#### Substitución

O método redefinido na subclase “substitúe” o comportamento do método herdado. Os métodos substituídos nas subclases márcanse coa anotación **`@Override`**<i class="fa-copy">:copy:</i>. Indica que o método é unha substitución dun método da superclase.

Sería o caso do método emitirSonido(), que se debe de redefinir:

```java
@Override //Esta etiqueta é opcional
public void emitirSonido(){
  System.out.println("O paxaro está a piar");
}
```

O uso da anotación @Override:

* **É altamente recomendable para a sobreescritura de métodos herdados directamente da clase Object** (toString(), equals(), hashCode(),...), xa que de non facelo, crea un novo método en lugar de sobreescribilo.
* No resto de casos, o seu uso é unha **moi boa práctica e 100%recomendable**, aínda que é opcional:
  * O compilador verifica que o método existe en la superclase
  * Evita errores tipográficos
  * Mejora a lexibilidade do código
  * Indica claramente a intención do programador
* Non se poden sobreescribir:
  * Métodos `final`
  * Métodos `private`
  * Métodos `static` (só se ocultan, non se sobreescriben)

Con todo, **é altamente recomendable**, especialmente nestes métodos, xa que permite ao compilador comprobar que a sinatura é correcta e evita que, por erro, se cree un método novo en lugar de sobreescribir o existente.

#### Redefinición

Definese un método co mesmo nome, tipo de retorno e parámetros que o método na superclase.

```java
@Override
public String describir() {
        return super.describir() + ", Color de plumas: " + this.getColorPlumas() 
                + ", Numero de dedos: " + this.getNumeroDedos();
}
```

Neste caso, o método reutiliza a funcionalidade implementada no método do pai e a complementa cos atributos da clase filla.

```java
Paxaro paloma = new Paxaro("Paloma","Gris",3);
paloma.emitirSonido();
System.out.println(paloma.describir());
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://educacion.gitbook.io/programacion/ud4-elementos-da-programacion-orientada-a-obxectos/herdanza.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
