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

Последнее обновление: 01.01.2022

Интерфейсы, как и классы, могут наследоваться:

interface IAction
{
	void Move();
}
interface IRunAction : IAction
{
	void Run();
}
class BaseAction : IRunAction
{
	public void Move()
	{
		Console.WriteLine("Move");
	}
	public void Run()
	{
		Console.WriteLine("Run");
	}
}

При применении этого интерфейса класс BaseAction должен будет реализовать как методы и свойства интерфейса IRunAction, так и методы и свойства базового интерфейса IAction, если эти методы и свойства не имеют реализации по умолчанию.

Однако в отличие от классов мы не можем применять к интерфейсам модификатор sealed, чтобы запретить наследование интерфейсов.

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

Однако методы интерфейсов могут использовать ключевое слово new для скрытия методов из базового интерфейса:

IAction action1 = new RunAction();
action1.Move(); // I am moving

IRunAction action2 = new RunAction();
action2.Move(); // I am running

interface IAction
{
    void Move() => Console.WriteLine("I am moving");
}
interface IRunAction : IAction
{
    // скрываем реализацию из IAction
    new void Move() => Console.WriteLine("I am running");
}
class RunAction : IRunAction { }

Здесь метод Move из IRunAction скрывает метод Move из базового интерфейса IAction. Это имеет смысл, если в базовом интерфейсе определена реализация по умолчанию, как в случае выше, которую нужно переопределить. И в случае выше, если переменная представляет тип IRunAction, то для метода Move вызывается реализация этого интерфейса:

IRunAction action2 = new RunAction();
action2.Move(); // I am running

Иначе если переменная представляет тип IAction, то для метода Move применяется реализация этого интерфейса:

IAction action1 = new RunAction();
action1.Move(); // I am moving

Но класс RunAction может переопределить метод Move сразу для обоих интерфейсов.

IAction action1 = new RunAction();
action1.Move(); // I am tired

IRunAction action2 = new RunAction();
action2.Move(); // I am tired

interface IAction
{
    void Move() => Console.WriteLine("I am moving");
}
interface IRunAction : IAction
{
    new void Move() => Console.WriteLine("I am running");
}
class RunAction : IRunAction
{
    public void Move() => Console.WriteLine("I am tired");
}

При наследовании интерфейсов следует учитывать, что, как и при наследовании классов, производный интерфейс должен иметь тот же уровень доступа или более строгий, чем базовый интерфейс. Например:

public interface IAction
{
	void Move();
}
internal interface IRunAction : IAction
{
	void Run();
}

Но не наоборот. Например, в следующем случае мы получим ошибку, и программа не скомпилируется, так как производный интерфейс имеет менее строгий уровень доступа, нежели базовый:

internal interface IAction
{
	void Move();
}
public interface IRunAction : IAction	// ошибка IRunAction может быть только internal
{
	void Run();
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850