Множественные интерфейсы
Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy — урок 27 из 70.
Хотя класс может наследоваться только от одного базового класса, он может реализовывать столько интерфейсов, сколько необходимо. Это одно из ключевых преимуществ интерфейсов перед абстрактными классами — они позволяют классу принимать несколько вариантов поведения.
Для реализации нескольких интерфейсов просто перечислите их после двоеточия через запятую:
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");
}
}Класс Duck должен реализовывать все члены обоих интерфейсов. Это естественным образом моделирует сценарии реального мира — утка действительно может и летать, и плавать, поэтому для неё логично выполнять оба контракта.
При сочетании наследования с несколькими интерфейсами базовый класс должен идти первым:
public class Duck : Bird, IFlyable, ISwimmable
{
// Наследуется от Bird, реализует оба интерфейса
}Эта гибкость позволяет вам компоновать поведение из нескольких источников. Robot может реализовывать IMovable, IChargeable и ISpeakable. Каждый интерфейс представляет собой отдельную возможность, и ваш класс может комбинировать именно то, что ему нужно.
Задание
ЛегкоДавайте создадим систему устройств для умного дома, которая демонстрирует, как один класс может реализовывать несколько интерфейсов для получения различных возможностей. Вы создадите устройства, которые могут быть как управляемыми, так и иметь функции сетевого подключения.
Вы организуете свой код в четырех файлах:
IControllable.cs: Определите интерфейс с именемIControllableв пространстве именSmartHome. Этот интерфейс представляет устройства, которые можно включать и выключать. Он должен объявлять два метода:TurnOn()иTurnOff(), оба возвращающие строку.INetworkConnected.cs: Определите интерфейс с именемINetworkConnectedв пространстве именSmartHome. Этот интерфейс представляет устройства, которые могут подключаться к сети. Он должен объявлять методConnect(string network), который возвращает строку.SmartTV.cs: Определите классSmartTVв пространстве именSmartHome, который реализует какIControllable, так иINetworkConnected. У телевизора должно быть свойствоBrand(string) и свойствоScreenSize(int, представляющее дюймы). Создайте конструктор, принимающий оба значения. Реализуйте все методы интерфейса:TurnOn()возвращает"{Brand} {ScreenSize}-inch TV is now ON"TurnOff()возвращает"{Brand} {ScreenSize}-inch TV is now OFF"Connect(string network)возвращает"{Brand} TV connected to {network}"
Program.cs: В вашем основном файле создайте объектSmartTV, используя входные значения. Продемонстрируйте гибкость нескольких интерфейсов, сохранив один и тот же объект телевизора в переменных трех разных типов: конкретный типSmartTV, переменнаяIControllableи переменнаяINetworkConnected. Вызовите соответствующие методы через каждую ссылку, чтобы показать, как один и тот же объект может обрабатываться по-разному в зависимости от того, с каким интерфейсом вы работаете.
Вы получите три входных значения:
- Название бренда телевизора
- Размер экрана в дюймах
- Название сети для подключения
Выведите результат в следующем формате:
Via SmartTV:
{TurnOn() result}
{Connect(network) result}
Via IControllable:
{TurnOff() result}
Via INetworkConnected:
{Connect(network) result}Например, если входные данные — Samsung, 55 и HomeWiFi, вывод должен быть следующим:
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 HomeWiFiОбратите внимание, как к одному и тому же объекту SmartTV можно обращаться через ссылки на разные интерфейсы. При хранении в качестве IControllable вы можете вызывать только методы управления. При хранении в качестве INetworkConnected вы можете вызывать только сетевые методы. В этом и заключается сила реализации нескольких интерфейсов — один класс получает множество возможностей, оставаясь гибким в использовании!
Шпаргалка
Класс может реализовывать несколько интерфейсов, перечисляя их через запятую после двоеточия:
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");
}
}Класс должен реализовать все члены всех указанных интерфейсов.
При сочетании наследования с несколькими интерфейсами базовый класс должен указываться первым:
public class Duck : Bird, IFlyable, ISwimmable
{
// Inherits from Bird, implements both interfaces
}Это позволяет компоновать поведение из нескольких источников, где каждый интерфейс представляет собой отдельную возможность.
Попробуйте сами
using System;
using SmartHome;
class Program
{
public static void Main(string[] args)
{
// Чтение входных данных
string brand = Console.ReadLine();
int screenSize = Convert.ToInt32(Console.ReadLine());
string network = Console.ReadLine();
// TODO: Создайте объект SmartTV с входными значениями
// TODO: Сохраните один и тот же объект TV в переменных трех разных типов:
// 1. Тип SmartTV (конкретный класс)
// 2. Тип IControllable (ссылка на интерфейс)
// 3. Тип INetworkConnected (ссылка на интерфейс)
// TODO: Выведите результат в требуемом формате:
// Через SmartTV:
// - Вызовите TurnOn() и Connect(network)
// Через IControllable:
// - Вызовите TurnOff()
// Через INetworkConnected:
// - Вызовите Connect(network)
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыПространства имен и директивыВведение в классы и объектыКлючевое слово 'this'Методы и параметрыПоля и свойстваКонструкторыИнициализаторы объектовИтоги — Простой калькулятор4Наследование
Основы синтаксиса наследования (:)Ключевое слово 'base'Ключевые слова Virtual и OverrideЗапечатанные классыБазовый класс 'object'Итоги — Иерархия сотрудников7Продвинутые возможности
Перегрузка операторовИндексаторы (this[])Переопределение ToString()Методы расширенияПовторение — Пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПотокобезопасный SingletonПаттерн FactoryПаттерн Observer (События)Паттерн Strategy13Финальные испытания
Платформа для онлайн-обученияКомпонент игрового персонажаСервис аренды транспорта2Свойства и статические члены
Автоматически реализуемые свойстваСвойства только для чтения и записиСтатические поля и методыСтатические классыЧлены в виде выражений5Полиморфизм и интерфейсы
Полиморфизм: компиляция vs выполнениеИнтерфейс vs абстрактный классМножественные интерфейсыЯвные интерфейсыUpcasting и DowncastingИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция вместо наследованияGenerics (классы и методы)Делегаты и событияАтрибуты и рефлексияIDisposable и оператор usingОсновы Dependency Injection11Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн Компоновщик3Архитектура классов
Экземплярные и статические данныеКлючевые слова 'readonly' и 'const'Опорные поляПовторение — Менеджер банковских счетов6Инкапсуляция
Модификаторы доступаСвойства для инкапсуляцииРеализация скрытия данныхПаттерны неизменяемостиИтоги — Записи студентов9Переменное количество аргументов
Ключевое слово 'params'Необязательные параметрыИменованные аргументыПерегрузка методов