Múltiplas Interfaces
Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy — lição 27 de 70.
Embora uma classe possa herdar de apenas uma classe base, ela pode implementar tantas interfaces quantas forem necessárias. Esta é uma das principais vantagens que as interfaces têm sobre as classes abstratas - elas permitem que uma classe adote múltiplos comportamentos.
Para implementar múltiplas interfaces, basta listá-las após os dois pontos, separadas por vírgulas:
public interface IFlyable
{
void Fly();
}
public interface ISwimmable
{
void Swim();
}
public class Duck : IFlyable, ISwimmable
{
public void Fly()
{
Console.WriteLine("Flying through the air");
}
public void Swim()
{
Console.WriteLine("Swimming in the pond");
}
}A classe Duck deve implementar todos os membros de ambas as interfaces. Isso modela cenários do mundo real naturalmente - um pato genuinamente pode tanto voar quanto nadar, então faz sentido que ele cumpra ambos os contratos.
Ao combinar herança com múltiplas interfaces, a classe base deve vir primeiro:
public class Duck : Bird, IFlyable, ISwimmable
{
// Herda de Bird, implementa ambas as interfaces
}Essa flexibilidade permite que você componha comportamentos de múltiplas fontes. Um Robot pode implementar IMovable, IChargeable e ISpeakable. Cada interface representa uma única capacidade, e sua classe pode combinar exatamente o que precisa.
Desafio
FácilVamos construir um sistema de dispositivos domésticos inteligentes que demonstra como uma única classe pode implementar múltiplas interfaces para obter diferentes capacidades. Você criará dispositivos que podem ser controláveis e ter recursos de gerenciamento de energia.
Você organizará seu código em quatro arquivos:
IControllable.cs: Defina uma interface chamadaIControllableno namespaceSmartHome. Esta interface representa dispositivos que podem ser ligados e desligados. Ela deve declarar dois métodos:TurnOn()eTurnOff(), ambos retornando uma string.INetworkConnected.cs: Defina uma interface chamadaINetworkConnectedno namespaceSmartHome. Esta interface representa dispositivos que podem se conectar a uma rede. Ela deve declarar um métodoConnect(string network)que retorna uma string.SmartTV.cs: Defina uma classeSmartTVno namespaceSmartHomeque implementa tantoIControllablequantoINetworkConnected. A TV deve ter uma propriedadeBrand(string) e uma propriedadeScreenSize(int, representando polegadas). Crie um construtor que aceite ambos os valores. Implemente todos os métodos da interface:TurnOn()retorna"{Brand} {ScreenSize}-inch TV is now ON"TurnOff()retorna"{Brand} {ScreenSize}-inch TV is now OFF"Connect(string network)retorna"{Brand} TV connected to {network}"
Program.cs: No seu arquivo principal, crie umaSmartTVusando valores de entrada. Demonstre a flexibilidade de múltiplas interfaces armazenando o mesmo objeto TV em três tipos de variáveis diferentes: o tipo concretoSmartTV, uma variávelIControllablee uma variávelINetworkConnected. Chame os métodos apropriados através de cada referência para mostrar como o mesmo objeto pode ser tratado de forma diferente dependendo de qual interface você está trabalhando.
Você receberá três entradas:
- Nome da marca da TV
- Tamanho da tela em polegadas
- Nome da rede para se conectar
Imprima a saída neste formato:
Via SmartTV:
{TurnOn() result}
{Connect(network) result}
Via IControllable:
{TurnOff() result}
Via INetworkConnected:
{Connect(network) result}Por exemplo, se as entradas forem Samsung, 55, e HomeWiFi, a saída deve ser:
Via SmartTV:
Samsung 55-inch TV is now ON
Samsung TV connected to HomeWiFi
Via IControllable:
Samsung 55-inch TV is now OFF
Via INetworkConnected:
Samsung TV connected to HomeWiFiObserve como o mesmo objeto SmartTV pode ser acessado através de diferentes referências de interface. Quando armazenado como IControllable, você só pode chamar métodos de controle. Quando armazenado como INetworkConnected, você só pode chamar métodos de rede. Este é o poder de implementar múltiplas interfaces - uma classe ganha múltiplas capacidades enquanto permanece flexível em como é usada!
Folha de consulta
Uma classe pode implementar múltiplas interfaces listando-as após os dois pontos, separadas por vírgulas:
public interface IFlyable
{
void Fly();
}
public interface ISwimmable
{
void Swim();
}
public class Duck : IFlyable, ISwimmable
{
public void Fly()
{
Console.WriteLine("Flying through the air");
}
public void Swim()
{
Console.WriteLine("Swimming in the pond");
}
}A classe deve implementar todos os membros de todas as interfaces.
Ao combinar herança com múltiplas interfaces, a classe base deve vir primeiro:
public class Duck : Bird, IFlyable, ISwimmable
{
// Herda de Bird, implementa ambas as interfaces
}Isso permite compor comportamentos de múltiplas fontes, com cada interface representando uma única capacidade.
Experimente você mesmo
using System;
using SmartHome;
class Program
{
public static void Main(string[] args)
{
// Ler entradas
string brand = Console.ReadLine();
int screenSize = Convert.ToInt32(Console.ReadLine());
string network = Console.ReadLine();
// TODO: Criar um objeto SmartTV com os valores de entrada
// TODO: Armazenar o mesmo objeto TV em três tipos de variáveis diferentes:
// 1. Tipo SmartTV (classe concreta)
// 2. Tipo IControllable (referência de interface)
// 3. Tipo INetworkConnected (referência de interface)
// TODO: Imprimir a saída no formato exigido:
// Via SmartTV:
// - Chamar TurnOn() e Connect(network)
// Via IControllable:
// - Chamar TurnOff()
// Via INetworkConnected:
// - Chamar Connect(network)
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosNamespaces e DiretivasIntrodução a Classes e ObjetosA Palavra-chave 'this'Métodos e ParâmetrosCampos vs PropriedadesConstrutoresInicializadores de ObjetosRecapitulação - Calculadora Simples4Herança
Sintaxe Básica de Herança (:)A Palavra-chave 'base'Palavras-chave Virtual e OverrideClasses SeladasA Classe Base 'object'Recapitulação - Hierarquia de Funcionários7Recursos Avançados
Sobrecarga de OperadoresIndexadores (this[])Sobrescrita de ToString()Métodos de ExtensãoRecapitulação - Lista Personalizada10Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoSingleton Thread-SafePadrão FactoryPadrão Observer (Eventos)Padrão Strategy2Propriedades e Membros Estáticos
Propriedades AutoimplementadasPropriedades de Apenas Leitura/EscritaCampos e Métodos EstáticosClasses EstáticasMembros com Corpo de Expressão5Polimorfismo e Interfaces
Polimorfismo: Compilação vs ExecuçãoInterface vs Classe AbstrataMúltiplas InterfacesInterfaces ExplícitasUpcasting e DowncastingRecapitulação - Calculadora de Formas8Conceitos Avançados de POO
Composição sobre HerançaGenerics (Classes e Métodos)Delegates e EventosAtributos e ReflectionIDisposable e a Instrução usingFundamentos de Injeção de Dependência11Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite3Arquitetura de Classes
Dados de Instância vs EstáticosPalavras-chave 'readonly' e 'const'Campos de SuporteRecapitulação - Gerenciador de Conta Bancária6Encapsulamento
Modificadores de AcessoPropriedades para EncapsulamentoImplementação de Ocultação de DadosPadrões de ImutabilidadeRecapitulação - Registros de Estudantes9Argumentos Variáveis
A Palavra-chave 'params'Parâmetros OpcionaisArgumentos NomeadosSobrecarga de Métodos