СДЕЛАЙТЕ СВОИ УРОКИ ЕЩЁ ЭФФЕКТИВНЕЕ, А ЖИЗНЬ СВОБОДНЕЕ

Благодаря готовым учебным материалам для работы в классе и дистанционно

Скидки до 50 % на комплекты
только до

Готовые ключевые этапы урока всегда будут у вас под рукой

Организационный момент

Проверка знаний

Объяснение материала

Закрепление изученного

Итоги урока

Интерфейсы. Применение интерфейсов

Категория: Информатика

Нажмите, чтобы узнать подробности

Просмотр содержимого документа
«Интерфейсы. Применение интерфейсов»

Интерфейсы. Применение интерфейсов

Интерфейсы. Применение интерфейсов

Интерфейс представляет ссылочный тип, который может определять некоторый функционал - набор методов и свойств без реализации. Затем этот функционал реализуют классы и структуры, которые применяют данные интерфейсы.
  • Интерфейс представляет ссылочный тип, который может определять некоторый функционал - набор методов и свойств без реализации. Затем этот функционал реализуют классы и структуры, которые применяют данные интерфейсы.
Определение интерфейса Для определения интерфейса используется ключевое слово  interface . Как правило, названия интерфейсов в C# начинаются с заглавной буквы  I , например, IComparable, IEnumerable (так называемая венгерская нотация), однако это не обязательное требование, а больше стиль программирования.

Определение интерфейса

  • Для определения интерфейса используется ключевое слово  interface . Как правило, названия интерфейсов в C# начинаются с заглавной буквы  I , например, IComparable, IEnumerable (так называемая венгерская нотация), однако это не обязательное требование, а больше стиль программирования.
Что может определять интерфейс? В целом интерфейсы могут определять следующие сущности: Методы Свойства Индексаторы События Статические поля и константы (начиная с версии C# 8.0)
  • Что может определять интерфейс? В целом интерфейсы могут определять следующие сущности:
  • Методы
  • Свойства
  • Индексаторы
  • События
  • Статические поля и константы (начиная с версии C# 8.0)
Однако интерфейсы не могут определять нестатические переменные. Например, простейший интерфейс, который определяет все эти компоненты:
  • Однако интерфейсы не могут определять нестатические переменные. Например, простейший интерфейс, который определяет все эти компоненты:
В данном случае определен интерфейс IMovable, который представляет некоторый движущийся объект. Данный интерфейс содержит различные компоненты, которые описывают возможности движущегося объекта. То есть интерфейс описывает некоторый функционал, который должен быть у движущегося объекта.
  • В данном случае определен интерфейс IMovable, который представляет некоторый движущийся объект. Данный интерфейс содержит различные компоненты, которые описывают возможности движущегося объекта. То есть интерфейс описывает некоторый функционал, который должен быть у движущегося объекта.
Методы и свойства интерфейса могут не иметь реализации, в этом они сближаются с абстрактными методами и свойствами абстрактных классов. В данном случае интерфейс определяет метод Move, который будет представлять некоторое передвижение. Он не имеет реализации, не принимает никаких параметров и ничего не возвращает.
  • Методы и свойства интерфейса могут не иметь реализации, в этом они сближаются с абстрактными методами и свойствами абстрактных классов. В данном случае интерфейс определяет метод Move, который будет представлять некоторое передвижение. Он не имеет реализации, не принимает никаких параметров и ничего не возвращает.
То же самое в данном случае касается свойства Name. На первый взгляд оно похоже на автоматическое свойство. Но в реальности это определение свойства в интерфейсе, которое не имеет реализации, а не автосвойство.
  • То же самое в данном случае касается свойства Name. На первый взгляд оно похоже на автоматическое свойство. Но в реальности это определение свойства в интерфейсе, которое не имеет реализации, а не автосвойство.
Модификаторы доступа Еще один момент в объявлении интерфейса: если его члены - методы и свойства не имеют модификаторов доступа, то фактически по умолчанию доступ  public , так как цель интерфейса - определение функционала для реализации его классом. Это касается также и констант и статических переменных, которые в классах и структурах по умолчанию имеют модификатор private. В интерфейсах же они имеют по умолчанию модификатор public. 

Модификаторы доступа

  • Еще один момент в объявлении интерфейса: если его члены - методы и свойства не имеют модификаторов доступа, то фактически по умолчанию доступ  public , так как цель интерфейса - определение функционала для реализации его классом. Это касается также и констант и статических переменных, которые в классах и структурах по умолчанию имеют модификатор private. В интерфейсах же они имеют по умолчанию модификатор public. 
И например, мы могли бы обратиться к константе minSpeed и переменной maxSpeed интерфейса IMovable:
  • И например, мы могли бы обратиться к константе minSpeed и переменной maxSpeed интерфейса IMovable:
Но также, начиная с версии C# 8.0, мы можем явно указывать модификаторы доступа у компонентов интерфейса:
  • Но также, начиная с версии C# 8.0, мы можем явно указывать модификаторы доступа у компонентов интерфейса:
Как и классы, интерфейсы по умолчанию имеют уровень доступа  internal , то есть такой интерфейс доступен только в рамках текущего проекта. Но с помощью модификатора public мы можем сделать интерфейс общедоступным:
  • Как и классы, интерфейсы по умолчанию имеют уровень доступа  internal , то есть такой интерфейс доступен только в рамках текущего проекта. Но с помощью модификатора public мы можем сделать интерфейс общедоступным:
Реализация по умолчанию Также начиная с версии C# 8.0 интерфейсы поддерживают реализацию методов и свойств по умолчанию. Это значит, что мы можем определить в интерфейсах полноценные методы и свойства, которые имеют реализацию как в обычных классах и структурах.

Реализация по умолчанию

  • Также начиная с версии C# 8.0 интерфейсы поддерживают реализацию методов и свойств по умолчанию. Это значит, что мы можем определить в интерфейсах полноценные методы и свойства, которые имеют реализацию как в обычных классах и структурах.
Например, определим реализацию метода Move по умолчанию:
  • Например, определим реализацию метода Move по умолчанию:
С реализацией свойств по умолчанию в интерфейсах дело обстоит несколько сложнее, поскольку мы не можем определять в интерфейсах нестатические переменные, соответственно в свойствах интерфейса мы не можем манипулировать состоянием объекта.
  • С реализацией свойств по умолчанию в интерфейсах дело обстоит несколько сложнее, поскольку мы не можем определять в интерфейсах нестатические переменные, соответственно в свойствах интерфейса мы не можем манипулировать состоянием объекта.
Тем не менее реализацию по умолчанию для свойств мы тоже можем определять:
  • Тем не менее реализацию по умолчанию для свойств мы тоже можем определять:
Стоит отметить, что если интерфейс имеет приватные методы и свойства (то есть с модификатором private), то они должны иметь реализацию по умолчанию. То же самое относится к статическим методам (не обязательно приватным):
  • Стоит отметить, что если интерфейс имеет приватные методы и свойства (то есть с модификатором private), то они должны иметь реализацию по умолчанию. То же самое относится к статическим методам (не обязательно приватным):
 New Item...  и в диалоговом окне добавления нового компонента выбрать пункт  Interface : " width="640"

Добавление интерфейса

  • Стоит отметить, что в Visual Studio есть специальный компонент для добавления нового интерфейса в отдельном файле. Для добавления интерфейса в проект можно нажать правой кнопкой мыши на проект и в появившемся контекстном меню выбрать  Add -  New Item...  и в диалоговом окне добавления нового компонента выбрать пункт  Interface :
Хотя мы также может добавить стандартный файл класса или любой другой файл кода C# и в нем определить интерфейс.

Хотя мы также может добавить стандартный файл класса или любой другой файл кода C# и в нем определить интерфейс.

Применение интерфейсов Интерфейс представляет некое описание типа, набор компонентов, который должен иметь тип данных. И, собственно, мы не можем создавать объекты интерфейса напрямую с помощью конструктора, как например, в классах :

Применение интерфейсов

  • Интерфейс представляет некое описание типа, набор компонентов, который должен иметь тип данных. И, собственно, мы не можем создавать объекты интерфейса напрямую с помощью конструктора, как например, в классах :
В конечном счете интерфейс предназначен для реализации в классах и структурах. Например, реализуем выше определенный интерфейс IMovable:
  • В конечном счете интерфейс предназначен для реализации в классах и структурах. Например, реализуем выше определенный интерфейс IMovable:
При применении интерфейса, как и при наследовании после имени класса или структуры указывается двоеточие и затем идут названия применяемых интерфейсов. При этом класс должен реализовать все методы и свойства применяемых интерфейсов, если эти методы и свойства не имеют реализации по умолчанию.
  • При применении интерфейса, как и при наследовании после имени класса или структуры указывается двоеточие и затем идут названия применяемых интерфейсов. При этом класс должен реализовать все методы и свойства применяемых интерфейсов, если эти методы и свойства не имеют реализации по умолчанию.
Если методы и свойства интерфейса не имеют модификатора доступа, то по умолчанию они являются публичными, при реализации этих методов и свойств в классе и структуре к ним можно применять только модификатор  public .

Если методы и свойства интерфейса не имеют модификатора доступа, то по умолчанию они

являются публичными, при реализации этих методов и свойств в классе и структуре к ним можно применять только модификатор  public .

Применение интерфейса в программе:
  • Применение интерфейса в программе:
В данной программе определен метод  DoAction() , который в качестве параметра принимает объект интерфейса IMovable. На момент написания кода мы можем не знать, что это будет за объект - какой-то класс или структура. Единственное, в чем мы можем быть уверены, что этот объект обязательно реализует метод Move и мы можем вызвать этот метод.

В данной программе определен метод  DoAction() , который в качестве параметра принимает объект

интерфейса IMovable. На момент написания кода мы можем не знать, что это будет за объект - какой-то класс

или структура. Единственное, в чем мы можем быть уверены, что этот объект обязательно реализует метод Move и мы можем вызвать этот метод.

Иными словами, интерфейс - это контракт, что какой-то определенный тип обязательно реализует некоторый функционал. Консольный вывод данной программы:
  • Иными словами, интерфейс - это контракт, что какой-то определенный тип обязательно реализует некоторый функционал.
  • Консольный вывод данной программы:
Реализация интерфейсов по умолчанию Начиная с версии C# 8.0 интерфейсы поддерживают реализацию методов и свойств по умолчанию. Зачем это нужно? Допустим, у нас есть куча классов, которые реализуют некоторый интерфейс. Если мы добавим в этот интерфейс новый метод, то мы будем обязаны реализовать этот метод во всех классах, применяющих данный интерфейс. Иначе подобные классы просто не будут компилироваться. Теперь вместо реализации метода во всех классах нам достаточно определить его реализацию по умолчанию в интерфейсе.

Реализация интерфейсов по умолчанию

  • Начиная с версии C# 8.0 интерфейсы поддерживают реализацию методов и свойств по умолчанию. Зачем это нужно? Допустим, у нас есть куча классов, которые реализуют некоторый интерфейс. Если мы добавим в этот интерфейс новый метод, то мы будем обязаны реализовать этот метод во всех классах, применяющих данный интерфейс. Иначе подобные классы просто не будут компилироваться. Теперь вместо реализации метода во всех классах нам достаточно определить его реализацию по умолчанию в интерфейсе.
Если класс не реализует метод, будет применяться реализация по умолчанию.
  • Если класс не реализует метод, будет применяться реализация по умолчанию.
В данном случае интерфейс  IMovable  определяет реализацию по умолчанию для метода  Move . Класс Person не реализует этот метод, поэтому он применяет реализацию по умолчанию в отличие от класса  Car , который определяет свою реализацию для метода Move.

В данном случае интерфейс  IMovable  определяет реализацию по умолчанию для метода  Move .

Класс Person не реализует этот метод, поэтому он применяет реализацию по умолчанию в

отличие от класса  Car , который определяет свою реализацию для метода Move.

Стоит отметить, что хотя для объекта класса  Person  мы можем вызвать метод  Move  - ведь класс  Person  применяет интерфейс  IMovable , тем не менее мы не можем написать так:

Стоит отметить, что хотя для объекта класса  Person  мы можем вызвать метод  Move  - ведь класс 

Person  применяет интерфейс  IMovable , тем не менее мы не можем написать так:

Множественная реализация интерфейсов Интерфейсы имеют еще одну важную функцию: в C# не поддерживается множественное наследование, то есть мы можем унаследовать класс только от одного класса , в отличие, скажем, от языка С++, где множественное наследование можно использовать. Интерфейсы позволяют частично обойти это ограничение, поскольку в C# классы и структуры могут реализовать сразу несколько интерфейсов.

Множественная реализация интерфейсов

  • Интерфейсы имеют еще одну важную функцию: в C# не поддерживается множественное наследование, то есть мы можем унаследовать класс только от одного класса , в отличие, скажем, от языка С++, где множественное наследование можно использовать. Интерфейсы позволяют частично обойти это ограничение, поскольку в C# классы и структуры могут реализовать сразу несколько интерфейсов.
Все реализуемые интерфейсы указываются через запятую :
  • Все реализуемые интерфейсы указываются через запятую :
Рассмотрим на примере:
  • Рассмотрим на примере:
В данном случае определены два интерфейса. Интерфейс IMessage определяет свойство Text, которое представляет текст сообщения. А интерфейс IPrintable определяет метод Print. Класс Message реализует оба интерфейса и затем применяется в программе.
  • В данном случае определены два интерфейса. Интерфейс IMessage определяет свойство Text, которое представляет текст сообщения. А интерфейс IPrintable определяет метод Print.
  • Класс Message реализует оба интерфейса и затем применяется в программе.
Интерфейсы в преобразованиях типов Все сказанное в отношении преобразования типов характерно и для интерфейсов. Поскольку класс Message реализует интерфейс IMessage, то переменная типа IMessage может хранить ссылку на объект типа Message:

Интерфейсы в преобразованиях типов

  • Все сказанное в отношении преобразования типов характерно и для интерфейсов. Поскольку класс Message реализует интерфейс IMessage, то переменная типа IMessage может хранить ссылку на объект типа Message:
Преобразование от класса к его интерфейсу, как и преобразование от производного типа к базовому, выполняется автоматически. Так как любой объект Message реализует интерфейс IMessage.
  • Преобразование от класса к его интерфейсу, как и преобразование от производного типа к базовому, выполняется автоматически. Так как любой объект Message реализует интерфейс IMessage.
Обратное преобразование - от интерфейса к реализующему его классу будет аналогично преобразованию от базового класса к производному. Так как не каждый объект IMessage является объектом Message (ведь интерфейс IMessage могут реализовать и другие классы), то для подобного преобразования необходима операция приведения типов. 
  • Обратное преобразование - от интерфейса к реализующему его классу будет аналогично преобразованию от базового класса к производному. Так как не каждый объект IMessage является объектом Message (ведь интерфейс IMessage могут реализовать и другие классы), то для подобного преобразования необходима операция приведения типов. 
И если мы хотим обратиться к методам класса Message, которые не определены в интерфейсе IMessage, но являются частью класса Message, то нам надо явным образом выполнить преобразование типов:
  • И если мы хотим обратиться к методам класса Message, которые не определены в интерфейсе IMessage, но являются частью класса Message, то нам надо явным образом выполнить преобразование типов:
Явная реализация интерфейсов Кроме неявного применения интерфейсов, существует также явная реализация интерфейса. При явной реализации указывается название метода или свойства вместе с названием интерфейса. При этом при реализации мы не можем использовать какие-либо модификаторы :

Явная реализация интерфейсов

  • Кроме неявного применения интерфейсов, существует также явная реализация интерфейса. При явной реализации указывается название метода или свойства вместе с названием интерфейса. При этом при реализации мы не можем использовать какие-либо модификаторы :
Следует учитывать, что при явной реализации интерфейса его методы и свойства  не являются  частью интерфейса класса. Поэтому напрямую через объект класса мы к ним обратиться не сможем :
  • Следует учитывать, что при явной реализации интерфейса его методы и свойства  не являются  частью интерфейса класса. Поэтому напрямую через объект класса мы к ним обратиться не сможем :
В какой ситуации может действительно понадобиться явная реализация интерфейса? Например, когда класс применяет несколько интерфейсов, но они имеют один и тот же метод с одним и тем же возвращаемым результатом и одним и тем же набором параметров:
  • В какой ситуации может действительно понадобиться явная реализация интерфейса? Например, когда класс применяет несколько интерфейсов, но они имеют один и тот же метод с одним и тем же возвращаемым результатом и одним и тем же набором параметров:
Класс Person определяет один метод  Study() , создавая одну общую реализацию для обоих примененных интерфейсов. И вне зависимости от того, будем ли мы рассматривать объект Person как объект типа ISchool или IUniversity, результат метода будет один и тот же.

Класс Person определяет один метод  Study() , создавая одну общую реализацию для обоих примененных интерфейсов. И вне зависимости от того, будем ли мы рассматривать объект Person как объект типа ISchool или IUniversity, результат метода будет один и тот же.

Чтобы разграничить реализуемые интерфейсы, надо явным образом применить интерфейс:
  • Чтобы разграничить реализуемые интерфейсы, надо явным образом применить интерфейс:
Использование:
  • Использование:
Другая ситуация, когда в базовом классе уже реализован интерфейс, но необходимо в производном классе по-своему реализовать интерфейс:
  • Другая ситуация, когда в базовом классе уже реализован интерфейс, но необходимо в производном классе по-своему реализовать интерфейс:
Несмотря на то, что базовый класс BaseAction уже реализовал интерфейс IAction, но производный класс по-своему реализует его. Применение классов:
  • Несмотря на то, что базовый класс BaseAction уже реализовал интерфейс IAction, но производный класс по-своему реализует его. Применение классов:
Модификаторы доступа Члены интерфейса могут иметь разные модификаторы доступа. Если модификатор доступа не public, а какой-то другой, то при реализации метода, свойства или события интерфейса в классах и структурах мы можем применять два способа.

Модификаторы доступа

  • Члены интерфейса могут иметь разные модификаторы доступа. Если модификатор доступа не public, а какой-то другой, то при реализации метода, свойства или события интерфейса в классах и структурах мы можем применять два способа.
Во-первых, можно также использовать явную реализацию интерфейса, реализовав все необходимые интерфейса без модификаторов доступа :
  • Во-первых, можно также использовать явную реализацию интерфейса, реализовав все необходимые интерфейса без модификаторов доступа :
В данном случае опять же надо учитывать, что напрямую мы можем обратиться к подобным методам, свойствам и событиям через переменную интерфейса, но не переменную класса.
  • В данном случае опять же надо учитывать, что напрямую мы можем обратиться к подобным методам, свойствам и событиям через переменную интерфейса, но не переменную класса.
Альтернативный вариант представляет неявная реализация с модификатором  public
  • Альтернативный вариант представляет неявная реализация с модификатором  public
В этом случае к методам, свойствам и событиям интейрфейса можно обращаться через переменную класса.
  • В этом случае к методам, свойствам и событиям интейрфейса можно обращаться через переменную класса.
Реализация интерфейсов в базовых и производных классах Если класс применяет интерфейс, то этот класс должен реализовать все методы и свойства интерфейса, которые не имеют реализации по умолчанию .

Реализация интерфейсов в базовых и производных классах

  • Если класс применяет интерфейс, то этот класс должен реализовать все методы и свойства интерфейса, которые не имеют реализации по умолчанию .
Однако также можно и не реализовать методы, сделав их абстрактными, переложив право их реализации на производные классы:
  • Однако также можно и не реализовать методы, сделав их абстрактными, переложив право их реализации на производные классы:
При реализации интерфейса учитываются также методы и свойства, унаследованные от базового класса. Например:
  • При реализации интерфейса учитываются также методы и свойства, унаследованные от базового класса. Например:
Здесь класс HeroAction реализует интерфейс IAction, однако для реализации метода Move из интерфейса применяется метод Move, унаследованный от базового класса BaseAction. Таким образом, класс HeroAction может не реализовать метод Move, так как этот метод уже определен в базовом классе BaseAction.
  • Здесь класс HeroAction реализует интерфейс IAction, однако для реализации метода Move из интерфейса применяется метод Move, унаследованный от базового класса BaseAction. Таким образом, класс HeroAction может не реализовать метод Move, так как этот метод уже определен в базовом классе BaseAction.
Следует отметить, что если класс одновременно наследует другой класс и реализует интерфейс, как в примере выше класс HeroAction, то название базового класса должно быть указано до реализуемых интерфейсов:
  • Следует отметить, что если класс одновременно наследует другой класс и реализует интерфейс, как в примере выше класс HeroAction, то название базового класса должно быть указано до реализуемых интерфейсов:
Изменение реализации интерфейсов в производных классах Может сложиться ситуация, что базовый класс реализовал интерфейс, но в классе-наследнике необходимо изменить реализацию этого интерфейса. Что в этом случае делать? В этом случае мы можем использовать либо переопределение, либо скрытие метода или свойства интерфейса.

Изменение реализации интерфейсов в производных классах

  • Может сложиться ситуация, что базовый класс реализовал интерфейс, но в классе-наследнике необходимо изменить реализацию этого интерфейса. Что в этом случае делать? В этом случае мы можем использовать либо переопределение, либо скрытие метода или свойства интерфейса.
Первый вариант - переопределение виртуальных/абстрактных методов:
  • Первый вариант - переопределение виртуальных/абстрактных методов:
В базовом классе BaseAction реализованный метод интерфейса определен как виртуальный (можно было бы также сделать его абстрактным), а в производном классе он переопределен.
  • В базовом классе BaseAction реализованный метод интерфейса определен как виртуальный (можно было бы также сделать его абстрактным), а в производном классе он переопределен.
При вызове метода через переменную интерфейса, если она ссылается на объект производного класса, будет использоваться реализация из производного класса:
  • При вызове метода через переменную интерфейса, если она ссылается на объект производного класса, будет использоваться реализация из производного класса:
Второй вариант - скрытие метода в производном классе:
  • Второй вариант - скрытие метода в производном классе:
Также используем эти классы:
  • Также используем эти классы:
Так как интерфейс реализован именно в классе BaseAction, то через переменную action2 можно обратиться только к реализации метода Move из базового класса BaseAction.
  • Так как интерфейс реализован именно в классе BaseAction, то через переменную action2 можно обратиться только к реализации метода Move из базового класса BaseAction.
Третий вариант - повторная реализация интерфейса в классе-наследнике:
  • Третий вариант - повторная реализация интерфейса в классе-наследнике:
В этом случае реализации этого метода из базового класса будет игнорироваться:
  • В этом случае реализации этого метода из базового класса будет игнорироваться:
Также стоит отметить, что в случае с переменной action1 по-прежнему действует ранее связывание, в силу которого через эту переменную можно вызвать реализацию метода Move только из базового класса, который эта переменная представляет.
  • Также стоит отметить, что в случае с переменной action1 по-прежнему действует ранее связывание, в силу которого через эту переменную можно вызвать реализацию метода Move только из базового класса, который эта переменная представляет.
Четвертый вариант: явная реализация интерфейса:
  • Четвертый вариант: явная реализация интерфейса:
В этом случае для переменной IAction будет использоваться явная реализация интерфейса IAction, а для переменной HeroAction по прежнему будет использоваться неявная реализация:
  • В этом случае для переменной IAction будет использоваться явная реализация интерфейса IAction, а для переменной HeroAction по прежнему будет использоваться неявная реализация:
Наследование интерфейсов Интерфейсы, как и классы, могут наследоваться :

Наследование интерфейсов

  • Интерфейсы, как и классы, могут наследоваться :
При применении этого интерфейса класс BaseAction должен будет реализовать как методы и свойства интерфейса IRunAction, так и методы и свойства базового интерфейса IAction, если эти методы и свойства не имеют реализации по умолчанию.
  • При применении этого интерфейса класс BaseAction должен будет реализовать как методы и свойства интерфейса IRunAction, так и методы и свойства базового интерфейса IAction, если эти методы и свойства не имеют реализации по умолчанию.
Однако в отличие от классов мы не можем применять к интерфейсам модификатор  sealed , чтобы запретить наследование интерфейсов.
  • Однако в отличие от классов мы не можем применять к интерфейсам модификатор  sealed , чтобы запретить наследование интерфейсов.
Также мы не можем применять к интерфейсам модификатор  abstract , поскольку интерфейс фактически итак, как правило, предоставляет абстрактный функционал, который должен быть реализован в классе или структуре (за исключением методов и свойств с реализацией по умолчанию).
  • Также мы не можем применять к интерфейсам модификатор  abstract , поскольку интерфейс фактически итак, как правило, предоставляет абстрактный функционал, который должен быть реализован в классе или структуре (за исключением методов и свойств с реализацией по умолчанию).
Однако методы интерфейсов могут использовать ключевое слово  new  для скрытия методов из базового интерфейса :
  • Однако методы интерфейсов могут использовать ключевое слово  new  для скрытия методов из базового интерфейса :
Здесь метод Move из IRunAction скрывает метод Move из базового интерфейса IAction. Это имеет смысл, если в базовом интерфейсе определена реализация по умолчанию, как в случае выше, которую нужно переопределить. И в случае выше, если переменная представляет тип IRunAction, то для метода Move вызывается реализация этого интерфейса:
  • Здесь метод Move из IRunAction скрывает метод Move из базового интерфейса IAction. Это имеет смысл, если в базовом интерфейсе определена реализация по умолчанию, как в случае выше, которую нужно переопределить. И в случае выше, если переменная представляет тип IRunAction, то для метода Move вызывается реализация этого интерфейса:
Иначе если переменная представляет тип IAction, то для метода Move применяется реализация этого интерфейса:
  • Иначе если переменная представляет тип IAction, то для метода Move применяется реализация этого интерфейса:
Но класс RunAction может переопределить метод Move сразу для обоих интерфейсов.
  • Но класс RunAction может переопределить метод Move сразу для обоих интерфейсов.
При наследовании интерфейсов следует учитывать, что, как и при наследовании классов, производный интерфейс должен иметь тот же уровень доступа или более строгий, чем базовый интерфейс. Например:
  • При наследовании интерфейсов следует учитывать, что, как и при наследовании классов, производный интерфейс должен иметь тот же уровень доступа или более строгий, чем базовый интерфейс. Например:
Но не наоборот. Например, в следующем случае мы получим ошибку, и программа не скомпилируется, так как производный интерфейс имеет менее строгий уровень доступа, нежели базовый:
  • Но не наоборот. Например, в следующем случае мы получим ошибку, и программа не скомпилируется, так как производный интерфейс имеет менее строгий уровень доступа, нежели базовый: