Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Dica
Novo no desenvolvimento de software? Comece primeiro com os tutoriais de Introdução . Você encontrará interfaces quando precisar definir o comportamento compartilhado entre tipos não relacionados.
Experimentou em outro idioma? As interfaces C# são semelhantes às interfaces em Java ou protocolos no Swift. Passe o olho pela seção de implementação explícita em busca de padrões específicos de C#.
Uma interface define um contrato: um grupo de métodos, propriedades, eventos e indexadores relacionados que um class ou struct deve implementar. As interfaces permitem que um único tipo implemente vários contratos, o que é importante porque o C# não dá suporte a várias heranças de classes. Os structs não podem herdar de outros structs ou classes, portanto, as interfaces são a única maneira de adicionar comportamento compartilhado entre tipos de struct.
O exemplo a seguir declara uma interface e uma classe que a implementa:
interface IEquatable<T>
{
bool Equals(T obj);
}
public class Car : IEquatable<Car>
{
public string? Make { get; set; }
public string? Model { get; set; }
public string? Year { get; set; }
public bool Equals(Car? car) =>
car is not null &&
(Make, Model, Year) == (car.Make, car.Model, car.Year);
}
Qualquer classe ou struct que implementa IEquatable<T> deve fornecer um Equals método que corresponda à assinatura da interface. Você pode contar com qualquer IEquatable<T> implementação para dar suporte à comparação de igualdade, independentemente do tipo concreto. Essa previsibilidade é o valor principal das interfaces.
Declarar uma interface
Defina uma interface com a interface palavra-chave. Por convenção, os nomes de interface começam com um capital I:
interface ILogger
{
void Log(string message);
string Name { get; }
}
As interfaces podem conter métodos, propriedades, eventos e indexadores. Uma interface não pode conter campos de instância, construtores de instância ou finalizadores. Os membros são public por padrão. Você pode especificar outros modificadores de acessibilidade quando necessário. Por exemplo, use internal para os membros que não devem estar visíveis fora do assembly.
Implementar uma interface
class ou struct lista as interfaces que implementa após dois pontos em sua declaração. A classe deve fornecer uma implementação para cada membro declarado na interface:
public class ConsoleLogger : ILogger
{
public string Name => "Console";
public void Log(string message) =>
Console.WriteLine($"[{Name}] {message}");
}
public class FileLogger : ILogger
{
public string Name => "File";
public void Log(string message)
{
// In a real app, write to a file
Console.WriteLine($"[{Name}] Writing to file: {message}");
}
}
Uma classe pode implementar várias interfaces, separadas por vírgulas. Ele deve fornecer implementações para todos os membros de cada interface que ele lista.
Implementação explícita
Às vezes, você precisa implementar um membro de interface sem torná-lo parte da API pública da classe. A implementação explícita qualifica o membro usando o nome da interface. O membro só pode ser acessado por meio de uma variável do tipo de interface:
interface IMetric
{
double GetDistance(); // Returns meters
}
interface IImperial
{
double GetDistance(); // Returns feet
}
public class Runway(double meters) : IMetric, IImperial
{
// Explicit implementation for IMetric
double IMetric.GetDistance() => meters;
// Explicit implementation for IImperial
double IImperial.GetDistance() => meters * 3.28084;
}
A implementação explícita é útil quando duas interfaces declaram membros com o mesmo nome ou quando você deseja manter a superfície pública da classe limpa. Para obter mais detalhes, consulte a Implementação da Interface Explícita.
Herança de interface
As interfaces podem herdar de uma ou mais interfaces. Uma classe que implementa uma interface derivada deve implementar todos os membros da interface derivada e todas as suas interfaces base:
interface IDrawable
{
void Draw();
}
interface IShape : IDrawable
{
double Area { get; }
}
public class Circle(double radius) : IShape
{
public double Area => Math.PI * radius * radius;
public void Draw() =>
Console.WriteLine($"Drawing circle with area {Area:F2}");
}
Uma classe que implementa IShape pode ser convertida implicitamente em IDrawable, porque IShape herda dela.
Interfaces versus classes abstratas
As interfaces e as classes abstratas definem contratos que os tipos derivados devem atender.
- Use uma classe abstrata quando tipos relacionados compartilham estado (campos), construtores ou membros não públicos. As classes abstratas permitem que você evolua uma hierarquia adicionando novos membros com comportamento padrão sem quebrar tipos derivados existentes.
- Use uma interface quando um tipo precisar atender a um contrato que corta hierarquias não relacionadas ou quando precisar implementar vários contratos. As interfaces não podem declarar campos de instância ou construtores, portanto, elas são mais adequadas para adicionar recursos a tipos que já têm uma classe base. Para cenários avançados, as interfaces também dão suporte a implementações de membro padrão.
Uma classe pode herdar de apenas uma classe base, mas pode implementar várias interfaces. Essa distinção geralmente torna as interfaces a melhor opção para definir recursos que cortam hierarquias de tipo.
Trabalhando com interfaces internas
Normalmente, você pode implementar uma interface interna com membros públicos, desde que todos os tipos na assinatura da interface estejam publicamente acessíveis. Quando uma interface usa tipos internos em suas assinaturas de membro, você deve usar a implementação explícita porque o membro em implementação não pode ser público ao expor tipos internos:
internal class InternalConfiguration
{
public string Setting { get; set; } = "";
}
internal interface ILoggable
{
void Log(string message);
}
internal interface IConfigurable
{
void Configure(InternalConfiguration config);
}
public class ServiceImplementation : ILoggable, IConfigurable
{
// Implicit implementation: ILoggable uses only public types in its signature
public void Log(string message) =>
Console.WriteLine($"Log: {message}");
// Explicit implementation: IConfigurable uses internal types
void IConfigurable.Configure(InternalConfiguration config) =>
Console.WriteLine($"Configured with: {config.Setting}");
}
No exemplo anterior, IConfigurable usa um tipo InternalConfiguration interno em sua assinatura de método.
ServiceImplementation faz uso de implementação explícita para aquele membro. Por outro lado, ILoggable usa apenas tipos públicos (string) em sua assinatura e pode ser implementado implicitamente.
Membros de interface padrão e membros abstratos estáticos
As interfaces dão suporte a dois recursos avançados que vão além dos contratos básicos:
- Os membros da interface padrão permitem que uma interface forneça um corpo do método. Os tipos que implementam herdam a implementação padrão e, opcionalmente, podem substituí-la. Para obter mais informações, consulte método de interface padrão.
- Membros abstratos estáticos exigem a implementação de tipos para fornecer um membro estático, o que é útil para definir contratos de operador ou padrões de fábrica. Para obter mais informações, consulte membros abstratos estáticos em interfaces.
Os dois recursos são abordados no artigo sobre interfaces na referência de linguagem. A maior parte do uso da interface diária envolve a declaração e a implementação de padrões descritos anteriormente neste artigo.
Resumo de interfaces
- Uma interface define um contrato de métodos, propriedades, eventos e indexadores.
- Uma classe ou struct que implementa uma interface deve fornecer implementações para todos os membros declarados (a menos que a interface forneça uma implementação padrão).
- Você não pode criar uma instância de uma interface diretamente.
- Uma classe ou struct pode implementar várias interfaces. Uma classe pode herdar uma classe base e também implementar uma ou mais interfaces.
- Os nomes de interface começam convencionalmente com
I.