DEV Community

Gabriel_Silvestre
Gabriel_Silvestre

Posted on

Introdução a Heranças e Interfaces

Tabela de Conteúdo


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.

class Animal {}

class Dog extends Animal {}
Enter fullscreen mode Exit fullscreen mode

Voltar ao topo


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.

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
}
Enter fullscreen mode Exit fullscreen mode

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.

class Animal {
  constructor() {}
}

class Dog extends Animal {
  constructor() {
    super();
  }
}
Enter fullscreen mode Exit fullscreen mode

Voltar ao topo


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.

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

  bark(): void;
}
Enter fullscreen mode Exit fullscreen mode

Voltar ao topo


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.

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

class BancoDeDados implements IBancoDeDados {
  save(data) {
    /* lógica para salvar no DB */
  }
}
Enter fullscreen mode Exit fullscreen mode
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);
  }
}
Enter fullscreen mode Exit fullscreen mode
const dataBase = new BancoDeDados();
const board = new Tabuleiro(['A1', 'A2', 'B1', 'B2'], dataBase);

board.save();
Enter fullscreen mode Exit fullscreen mode

Voltar ao topo


Links Úteis

Voltar ao topo

Discussion (0)