Introdução a Heranças e Interfaces
Tags: beginners, typescript, oop, braziliandevs
Published: 2022-05-18 20:21:09

## Tabela de Conteúdo
- [Herança](#herança)
- [Peculiaridades da Herança](#peculiaridades-na-herança)
- [Interfaces](#interfaces)
- [Composição](#composição)
- [Links Úteis](#links-úteis)

---

## Herança

### O que é?

É uma _"transferência de informações"_ entre uma Super Classe e uma Sub Classe, mas vai além de uma _"transferência"_ simples, trata-se de uma ligação, onde se a Super Classe sofre alteração as Sub Classes também sofrerão (o inverso não é verdadeiro).

### O que faz?

Como dito em sua definição, logo acima, permite o compartilhamento _(transferência)_ de código entre Classes, evitando a duplicidade de código e facilitando, se bem utilizada, a manutenção.

### Sintaxe

Para definirmos que uma Classe herda de outra utilizamos a palavra reservada `extends`, informando qual Classe está sendo herdada.

``` ts
class Animal {}

class Dog extends Animal {}
```

<br />

<small>[Voltar ao topo](#tabela-de-conteúdo)</small>

---

## Peculiaridades na Herança

### Atributos

Os atributos continuam com o mesmo encapsulamento mesmo em uma herança, ou seja, se determinado atributo é público podemos acessá-lo normalmente, porém se ele for privado precisaremos nos utilizar de métodos de acesso, assim como faríamos em uma instância da Classe.

Para podermos acessar atributos diretamente a partir de Sub Classes, porém ainda sim privar ele em instâncias, podemos utilizar o encapsulamento `protected`, dessa forma temos acesso direto dentro da Sub Classes, porém em Objetos ainda será necessário utilizar os métodos de acesso.

``` ts
class Animal {
  private specie: string;  // sem acesso em Sub Classes | sem acesso em instâncias
}

class Animal {
  protected specie: string;  // com acesso em Sub Classes | sem acesso em instâncias
}
```

### Super

O `super` é uma referência ao construtor da Super Classe dentro de uma Sub Classe, sendo necessário declará-lo sempre que a Super Classe tenha um construtor.

Isso é pelo fato de que a Sub Classe possui atributos e métodos em comum com a Super Classe, afinal realizamos uma herança, logo para que a Sub Classe exista é necessário que a Super Classe exista primeiro.

``` ts
class Animal {
  constructor() {}
}

class Dog extends Animal {
  constructor() {
    super();
  }
}
```

<br />

<small>[Voltar ao topo](#tabela-de-conteúdo)</small>

---

## Interfaces

### O que são?

Interfaces são _"contratos"_ que definem métodos e atributos públicos a serem declarados por qualquer classe que a implemente.

### O que fazem?

Definem uma série de regras a serem seguidas por qualquer classe que implemente determinada Interface, esse conjunto de regras não é funcional, ou seja, definimos apenas que a classe A deverá ter um método X, que tem um retorno do tipo Y, a funcionalidade será implementada posteriormente.

Fazendo um paralelo com Heranças, Interfaces irão definir apenas o _"esqueleto"_ dos métodos e atributos, restringindo seus nomes e tipos, enquanto as Heranças possuem métodos e atributos próprios com valores e funcionamentos previamente definidos.

### Sintaxe

A sintaxe para definirmos uma Interface é muito simples, tudo que precisamos fazer é utilizar a palavra reservada `interface`, seguida do nome que desejamos dar a ela, após isso abrimos chaves, definindo os nomes e tipos dos atributos e métodos.

``` ts
interface IDog {  // opcionalmente podemos colocar um "I" maiúsculo a frente de toda a interface
  name: string;
  age: number;

  bark(): void;
}
```

<br />

<small>[Voltar ao topo](#tabela-de-conteúdo)</small>

---

## Composição

## O que é?

É uma maneira de termos a disposição métodos e atributos de classes que não fazem sentido serem herdadas por outra determinada classe, por exemplo, imagine que temos uma API de xadrez, onde existem duas classes uma representa o DB e a outra representa o tabuleiro, sendo que queremos salvar o tabuleiro em nosso DB.

Não faz sentido a classe Tabuleiro herdar a classe BancoDeDados, pois um tabuleiro não é um tipo de DB, porém ainda sim precisamos das funcionalidades dessa classe para salvar nosso tabuleiro, nesse ponto entra a Composição.

### Sintaxe

Para realizarmos a Composição entre classes, tudo que precisamos fazer é indicar que uma classe recebe a instância de outra através de seu construtor, ou, retomando o exemplo anterior, a classe Tabuleiro irá receber a instância da classe BancoDeDados através dos parâmetros.

``` ts
interface IBancoDeDados {
  save(data: any): void;
}

class BancoDeDados implements IBancoDeDados {
  save(data) {
    /* lógica para salvar no DB */
  }
}
```

``` ts
interface ITabuleiro {
  boardData: string;
  save(): void;
}

class Tabuleiro implements ITabuleiro {
  constructor(
    public boardData: string,
    private bancoDeDados: IBancoDeDados  // é uma boa prática "tipar" outra classe a partir de sua Interface
  ) {}

  save() {
    this.bancoDeDados.save(this.boardData);
  }
}
```

``` ts
const dataBase = new BancoDeDados();
const board = new Tabuleiro(['A1', 'A2', 'B1', 'B2'], dataBase);

board.save();
```

<br />

<small>[Voltar ao topo](#tabela-de-conteúdo)</small>

---

## Links Úteis

- [YouTube - DevMedia](https://www.youtube.com/watch?v=qiGTRJlCnlA)
- [YouTube - Código Fonte TV](https://www.youtube.com/watch?v=QY0Kdg83orY)
- [Git Books - Introdução à Herança](https://manoelcampos.gitbooks.io/poo-java/content/chapter7.html) por Manoel dos Campos
- [TypeScript docs - Class Heritage](https://www.typescriptlang.org/docs/handbook/2/classes.html#class-heritage)
- [TypeScript docs - Extends Clauses](https://www.typescriptlang.org/docs/handbook/2/classes.html#extends-clauses)
- [TypeScript docs - Abstract Classes](https://www.typescriptlang.org/docs/handbook/2/classes.html#abstract-classes-and-members)

<br />

<small>[Voltar ao topo](#tabela-de-conteúdo)</small>