Interfaces - define o comportamento para vários tipos

Uma interface contém definições para um grupo de funcionalidades relacionadas que um não-abstrato class ou um struct deve implementar. Uma interface pode definir static métodos, que devem ter uma implementação. Uma interface pode definir uma implementação padrão para membros. Uma interface não pode declarar dados de instância, como campos, propriedades implementadas automaticamente ou eventos semelhantes a propriedades.

Usando interfaces, você pode, por exemplo, incluir o comportamento de várias fontes em uma classe. Esse recurso é importante em C# porque a linguagem não suporta herança múltipla de classes. Além disso, você deve usar uma interface se quiser simular herança para structs, porque eles não podem realmente herdar de outro struct ou classe.

Você define uma interface usando a interface palavra-chave como mostra o exemplo a seguir.

interface IEquatable<T>
{
    bool Equals(T obj);
}

O nome de uma interface deve ser um nome de identificador C# válido. Por convenção, os nomes das interfaces começam com maiúscula I.

Qualquer classe ou struct que implemente a IEquatable<T> interface deve conter uma definição para um Equals método que corresponda à assinatura especificada pela interface. Como resultado, você pode contar com uma classe de tipo T que implementa IEquatable<T> para conter um Equals método com o qual uma instância dessa classe pode determinar se é igual a outra instância da mesma classe.

A definição de IEquatable<T> não fornece uma implementação para Equals. Uma classe ou struct pode implementar várias interfaces, mas uma classe só pode herdar de uma única classe.

Para obter mais informações sobre classes abstratas, consulte Classes abstratas e seladas e Membros da classe.

As interfaces podem conter métodos de instância, propriedades, eventos, indexadores ou qualquer combinação desses quatro tipos de membros. As interfaces podem conter construtores, campos, constantes ou operadores estáticos. A partir do C# 11, os membros da interface que não são campos podem ser static abstract. Uma interface não pode conter campos de instância, construtores de instância ou finalizadores. Os membros da interface são públicos por padrão, e você pode especificar explicitamente modificadores de acessibilidade, como public, protected, internal, private, protected internalou private protected. Um private membro deve ter uma implementação padrão.

Para implementar um membro da interface, o membro correspondente da classe de implementação deve ser público, não estático e ter o mesmo nome e assinatura que o membro da interface.

Nota

Quando uma interface declara membros estáticos, um tipo que implementa essa interface também pode declarar membros estáticos com a mesma assinatura. Estes são distintos e identificados exclusivamente pelo tipo que declara o membro. O membro estático declarado em um tipo não substitui o membro estático declarado na interface.

Uma classe ou struct que implementa uma interface deve fornecer uma implementação para todos os membros declarados sem uma implementação padrão fornecida pela interface. No entanto, se uma classe base implementa uma interface, qualquer classe derivada da classe base herda essa implementação.

O exemplo a seguir mostra uma implementação da IEquatable<T> interface. A classe de implementação, Car, deve fornecer uma implementação do Equals método.

public class Car : IEquatable<Car>
{
    public string? Make { get; set; }
    public string? Model { get; set; }
    public string? Year { get; set; }

    // Implementation of IEquatable<T> interface
    public bool Equals(Car? car)
    {
        return (this.Make, this.Model, this.Year) ==
            (car?.Make, car?.Model, car?.Year);
    }
}

Propriedades e indexadores de uma classe podem definir acessadores extras para uma propriedade ou indexador definido em uma interface. Por exemplo, uma interface pode declarar uma propriedade que tenha um acessador get . A classe que implementa a interface pode declarar a mesma propriedade com um get acessador e set . No entanto, se a propriedade ou indexador usa implementação explícita, os acessadores devem corresponder. Para obter mais informações sobre implementação explícita, consulte Implementação de interface explícita e propriedades da interface.

As interfaces podem herdar de uma ou mais interfaces. A interface derivada herda os membros de suas interfaces base. Uma classe que implementa uma interface derivada deve implementar todos os membros na interface derivada, incluindo todos os membros das interfaces base da interface derivada. Essa classe pode ser implicitamente convertida para a interface derivada ou para qualquer uma das suas interfaces de base. Uma classe pode incluir uma interface várias vezes através de classes base que herda ou através de interfaces que outras interfaces herdam. No entanto, a classe pode fornecer uma implementação de uma interface apenas uma vez e somente se a classe declarar a interface como parte da definição da classe (class ClassName : InterfaceName). Se a interface é herdada porque você herdou uma classe base que implementa a interface, a classe base fornece a implementação dos membros da interface. No entanto, a classe derivada pode reimplementar qualquer membro da interface virtual em vez de usar a implementação herdada. Quando as interfaces declaram uma implementação padrão de um método, qualquer classe que implemente essa interface herda essa implementação (Você precisa converter a instância de classe para o tipo de interface para acessar a implementação padrão no membro Interface).

Uma classe base também pode implementar membros da interface usando membros virtuais. Nesse caso, uma classe derivada pode alterar o comportamento da interface substituindo os membros virtuais. Para obter mais informações sobre membros virtuais, consulte Polimorfismo.

Resumo das interfaces

Uma interface tem as seguintes propriedades:

  • Em versões C# anteriores à 8.0, uma interface é como uma classe base abstrata com apenas membros abstratos. Uma classe ou struct que implementa a interface deve implementar todos os seus membros.
  • A partir do C# 8.0, uma interface pode definir implementações padrão para alguns ou todos os seus membros. Uma classe ou struct que implementa a interface não precisa implementar membros que tenham implementações padrão. Para obter mais informações, consulte métodos de interface padrão.
  • Uma interface não pode ser instanciada diretamente. Seus membros são implementados por qualquer classe ou struct que implementa a interface.
  • Uma classe ou struct pode implementar várias interfaces. Uma classe pode herdar uma classe base e também implementar uma ou mais interfaces.