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.
Uma interface contém definições para um grupo de funcionalidades relacionadas que uma class ou um struct podem implementar. Uma interface pode definir static métodos. 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. Essa funcionalidade é importante em C# porque a linguagem não dá suporte a várias heranças de classes. Além disso, use uma interface se você deseja simular a herança para structs, pois eles não podem herdar de outro struct ou classe.
Você define uma interface usando a palavra-chave interface, como mostra o exemplo a seguir.
interface IEquatable<T>
{
bool Equals(T obj);
}
O nome da interface deve ser um nome do identificador válido em C#. Por convenção, os nomes de interface começam com uma letra maiúscula I.
Qualquer classe ou struct que implemente a interface IEquatable<T> deve conter uma definição para um método Equals que corresponda à assinatura que a interface especifica. Como resultado, você pode contar com uma classe do tipo T que implementa IEquatable<T> para conter um método Equals com o qual uma instância da 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 estrutura 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 e membros de classes abstratos e lacrados.
As interfaces podem conter métodos, propriedades, eventos, indexadores ou qualquer combinação desses quatro tipos de membros. As interfaces podem conter construtores estáticos, campos, constantes ou operadores. 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 membro private deve ter uma implementação padrão.
Para implementar um membro de interface usando a implementação implícita, 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. Você deve usar a implementação de interface explícita para implementar membros da interface que não devem ser públicos.
Observação
Quando uma interface declara membros estáticos, um tipo que implementa essa interface também pode declarar membros estáticos com a mesma assinatura. Esses membros são distintos e identificados exclusivamente pelo tipo que os declara. 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 implementar uma interface, qualquer classe derivada da classe base herdará essa implementação.
O exemplo a seguir mostra uma implementação da interface IEquatable<T>. A classe de implementação, Car, deverá fornecer uma implementação do método Equals.
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 declarado em uma interface. Por exemplo, uma interface pode declarar uma propriedade que tem um acessador get. A classe que implementa a interface pode declarar a mesma propriedade tanto com um acessador get quanto com um set. No entanto, se a propriedade ou o indexador usa a implementação explícita, os acessadores devem corresponder. Para obter mais informações sobre a implementação explícita, consulte Implementação de interface explícita e Propriedades da interface.
Uma interface pode 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 convertida implicitamente na interface derivada ou em qualquer uma de suas interfaces base. Uma classe pode incluir uma interface várias vezes por meio das classes base que ela herda ou por meio de interfaces que outras interfaces herdam. No entanto, a classe poderá fornecer uma implementação de uma interface apenas uma vez e somente se a classe declarar a interface como parte da definição de classe (class ClassName : InterfaceName). Se a interface é herdada porque é herdada de 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 de 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 da classe para o tipo de interface para acessar a implementação padrão no membro da interface).
Uma classe base também pode implementar membros de 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.
Trabalhando com interfaces internas
Uma interface interna normalmente pode ser implementada usando a implementação implícita com membros públicos, desde que todos os tipos na assinatura da interface estejam publicamente acessíveis. No entanto, quando uma interface usa tipos internos em suas assinaturas de membro, a implementação implícita torna-se impossível porque o membro da classe em implementação precisaria ser público ao expor tipos internos. Nesses casos, você deve usar a implementação de interface explícita.
O exemplo a seguir mostra os dois cenários:
// Internal type that cannot be exposed publicly
internal class InternalConfiguration
{
public string Setting { get; set; } = "";
}
// Internal interface that CAN be implemented with public members
// because it only uses public types in its signature
internal interface ILoggable
{
void Log(string message); // string is public, so this works with implicit implementation
}
// Interface with internal accessibility using internal types
internal interface IConfigurable
{
void Configure(InternalConfiguration config); // Internal type prevents implicit implementation
}
// This class shows both implicit and explicit interface implementation
public class ServiceImplementation : ILoggable, IConfigurable
{
// Implicit implementation works for ILoggable because string is public
public void Log(string message)
{
Console.WriteLine($"Log: {message}");
}
// Explicit implementation required for IConfigurable because it uses internal types
void IConfigurable.Configure(InternalConfiguration config)
{
// Implementation here
Console.WriteLine($"Configured with: {config.Setting}");
}
// If we tried implicit implementation for IConfigurable, this wouldn't compile:
// public void Configure(InternalConfiguration config) // Error: cannot expose internal type
}
No exemplo anterior, a IConfigurable interface usa um tipo InternalConfiguration interno em sua assinatura de método. A classe ServiceImplementation não pode usar implementação implícita porque isso exigiria tornar o método Configure público, o que não é permitido quando a assinatura do método contém tipos internos. Em vez disso, a implementação de interface explícita é usada, que não tem um modificador de acesso e só é acessível por meio do tipo de interface.
Por outro lado, a ILoggable interface pode ser implementada implicitamente com membros públicos porque todos os tipos em sua assinatura (string) são publicamente acessíveis, mesmo que a interface em si seja interna.
Para obter mais informações sobre a implementação da interface explícita, consulte a Implementação da Interface Explícita.
Resumo de interfaces
Uma interface tem as propriedades a seguir:
- Nas versões do C# anteriores à 8.0, uma interface é como uma classe base abstrata que contém apenas membros abstratos. Qualquer classe ou struct que implemente uma 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étodo de interface padrão.
- Uma interface não pode ser instanciada 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.