Skip to content

Classes Abstratas e Interfaces

No TypeScript, as classes abstratas e interfaces são ferramentas poderosas para a criação de estruturas de código mais robustas e flexíveis. Elas permitem a definição de contratos que as classes devem seguir, promovendo um desenvolvimento orientado a objetos mais organizado e seguro.

Classes Abstratas

Classes abstratas são semelhantes às classes normais, mas não podem ser instanciadas diretamente. Elas servem como modelos para outras classes. Uma classe abstrata pode definir métodos que as subclasses devem implementar, garantindo que todas as subclasses sigam um padrão específico.

Definindo Classes Abstratas:

Para definir uma classe abstrata, você usa a palavra-chave abstract antes da declaração da classe. Além disso, você pode definir métodos abstratos dentro dessa classe, que são métodos sem implementação que as subclasses são obrigadas a implementar.

typescript
abstract class Animal {
  // Método concreto com implementação
  move(): void {
    console.log("Moving along...");
  }

  // Método abstrato sem implementação
  abstract makeSound(): void;
}

Neste exemplo, a classe Animal possui um método concreto move e um método abstrato makeSound. Qualquer classe que herdar de Animal deve fornecer uma implementação para makeSound.

Implementando Classes Abstratas:

Ao estender uma classe abstrata, a classe derivada deve implementar todos os métodos abstratos definidos na classe abstrata.

typescript
class Dog extends Animal {
  // Implementação do método abstrato
  makeSound(): void {
    console.log("Woof! Woof!");
  }
}

const dog = new Dog();
dog.move(); // Saída: Moving along...
dog.makeSound(); // Saída: Woof! Woof!

Neste caso, a classe Dog estende Animal e fornece uma implementação para o método makeSound.

Interfaces

Interfaces definem a estrutura que uma classe deve seguir sem fornecer implementações. Elas são usadas para definir contratos em seu código e garantir que diferentes classes possam ser tratadas de maneira uniforme.

Definindo Interfaces:

Para definir uma interface, você usa a palavra-chave interface. Uma interface pode incluir propriedades e métodos, mas sem implementações.

typescript
interface Flyable {
  // Propriedade
  wings: number;

  // Método
  fly(): void;
}

Aqui, a interface Flyable define que qualquer classe que a implemente deve ter uma propriedade wings e um método fly.

Implementando Interfaces:

Uma classe pode implementar uma ou mais interfaces, garantindo que ela adere ao contrato definido pelas interfaces.

typescript
class Bird implements Flyable {
  // Implementação da propriedade
  wings: number;

  constructor(wings: number) {
    this.wings = wings;
  }

  // Implementação do método
  fly(): void {
    console.log("Flying high!");
  }
}

const bird = new Bird(2);
console.log(bird.wings); // Saída: 2
bird.fly(); // Saída: Flying high!

Neste exemplo, a classe Bird implementa a interface Flyable, garantindo que ela tenha a propriedade wings e o método fly.

Combinando Classes Abstratas e Interfaces

Classes abstratas e interfaces podem ser usadas juntas para fornecer uma estrutura ainda mais poderosa. Uma classe abstrata pode implementar uma interface e definir alguns métodos concretos enquanto deixa outros métodos como abstratos para serem implementados pelas subclasses.

typescript
interface Swimmable {
  swim(): void;
}

abstract class Fish implements Swimmable {
  // Implementação concreta do método da interface
  swim(): void {
    console.log("Swimming in the water...");
  }

  // Método abstrato
  abstract makeSound(): void;
}

class Shark extends Fish {
  makeSound(): void {
    console.log("Silent predator...");
  }
}

const shark = new Shark();
shark.swim(); // Saída: Swimming in the water...
shark.makeSound(); // Saída: Silent predator...

Neste exemplo, a classe abstrata Fish implementa a interface Swimmable e fornece uma implementação concreta para swim, mas deixa makeSound como um método abstrato para ser implementado pela subclasse Shark.

Resumo

  • Classes Abstratas: Servem como modelos para outras classes, podem ter métodos abstratos que devem ser implementados pelas subclasses.
  • Interfaces: Definem contratos que as classes devem seguir, sem fornecer implementações.
  • Combinação: Classes abstratas podem implementar interfaces e fornecer um esqueleto que subclasses concretas podem completar.

Esses conceitos são essenciais para a criação de código TypeScript bem estruturado e orientado a objetos, promovendo a reutilização e a manutenção de código mais eficiente.