Mateus Antunes

O que significa programar para uma interface e não para implementação?

July 16, 2021

À medida que um desenvolvedor começa explorar os padrões de projeto surgem conceitos que a primeiro momento parecem estranhos. Uma vez que entendido tais princípios torna-se possível construir sistemas com boa qualidade de design OO.

Um dos princípios de projeto que é bastante recorrente é:

Programe para uma interface e não para uma implementação.

Bom, agora vamos enter o que isso significa.

Interfaces

Primeiro vamos desassociar o conceito de Interfaces do conceito de programar para interface/ supertipo.

Na etapa de projeto de sistemas podemos definir um conjunto de classe que deverão implementar os métodos obrigatoriamente. Tais conjuntos de métodos são interfaces sem corpo, sem qualquer implementação. Porém, as classes que implementarem tal interface deverão obrigatoriamente definir métodos pré-definidos, caso contrário irá ocorrer um erro. Logo, quem implementar uma interface deve ser se responsabilizar e cumprir o contrato.

Uma interface apenas expõe o que o objeto deve fazer, e não como ele fazer, nem o que ele tem o que fazer. Esses detalhes ficam a cargo da implementação da classe.

Exemplo

Observe o diagrama abaixo:

exemplo interface

Temos as classes CanetaEsferografica, Lapis e Giz. Cada classe tem suas particularidades, mas também compartilham métodos semelhantes. As três classes estão implementando a interface Caneta. Então, essas classes obrigatoriamente vão implementar os métodos Escrever, bem como, GetCor da interface.

Programar para uma interface significa programar para um super tipo. Lembre-se, um supertipo pode ser representado através de:

  • Interfaces
  • Classes Abstratas

Perceba que que podemos utilizar mais de um conceito de orientação a objetos para programar para um super tipo. Você não precisa, necessariamente, usar uma interface para aplicar essa prática no seu código.

Exemplo com Classes Abstratas

No exemplo apresentado a seguir, será utilizado c# para ilustrar este conceito.

A classe animal possui os atributos de nome e comida. Além disso, tem os métodos abstratos falar e mover.

Esses métodos são uma especialização das classes filhas. Tais método serão sobreescritos pelas classes filhas. Perceba que o método comer é uma características gerenalizadas para todo tipo de animal.

public abstract class Animal
{
    public string name;
    public string food;

    public abstract void Talk();
    public abstract void Move();

    public void Eat()
    {
        Console.WriteLine($"{name} ate a lot of {food} today!");
    }
}

Abaixo, temos a classe cão que tem características da classe animal e implementa comportamentos específicos.

public class Dog : Animal
{
    public override void Talk()
    {
        Console.WriteLine("Woof! WOOF! :)");
    }

    public override void Move()
    {
        Console.WriteLine("I'm walking on 4 feet.");
    }
}

Por fim, temos a classe gato.

public class Cat : Animal
{
    public override void Talk()
    {
        Console.WriteLine("Woof! WOOF! :)");
    }

    public override void Move()
    {
        Console.WriteLine("I'm walking on 4 feet.");
    }
}

Programando para uma implementação concreta ficaria da seguite forma:

    Cat cat = new Cat();
    cat.name = "Tom";
    cat.food = "homework";

    cat.Eat();

    //output: Tom ate a lot of homework today!  

Programar para uma interface abstrata permite que seu código fique flexível a mudanças. No trecho de código abaixo, é possível observar que vários objetos de um mesmo tipo são tratados da mesma maneira.

    List<Animal> animals = new List<Animal>();

    Animal dog = new Dog();        
    dog.name = "Toto";
    dog.food = "homework";

    animals.Add(dog);

    Animal cat = new Cat();
    cat.name = "Tom";
    cat.food = "homework";

    animals.Add(cat);

    foreach(var animal in animals){
          animal.Eat();
    }

     //output: Toto ate a lot of homework today!
    //output: Tom ate a lot of homework today!

Conclusão

Por fim, o objeto desse artigo é introduzir apresentar o conceito de programação para interface.Podemos observar que programar para um supertipo possibilita explorar o polimorfismo em tempo de execução. Dessa forma, não vamos ficar presos a uma implementação específica.


Escrito por Mateus

© 2021, Mateus Antunes