В оставшихся главах книги вы встретите десятки интерфейсов, поставляемых в библиотеках базовых классов .NET Core. Вы увидите, что эти интерфейсы могут быть реализованы в собственных специальных классах и структурах для определения типов, которые тесно интегрированы с платформой. Вдобавок, как только вы оцените полезность интерфейсных типов, вы определенно найдете причины для построения собственных таких типов.
Сравнение интерфейсных типов и абстрактных базовых классов
Учитывая материалы главы 6, интерфейсный тип может выглядеть кое в чем похожим на абстрактный базовый класс. Вспомните, что когда класс помечен как абстрактный, он
Полиморфный интерфейс, устанавливаемый абстрактным родительским классом, обладает одним серьезным ограничением: члены, определенные абстрактным родительским классом, поддерживаются
System.Object. Учитывая, что абстрактные члены в абстрактном базовом классе применимы только к производным типам, не существует какого-то способа конфигурирования типов в разных иерархиях для поддержки одного и того же полиморфного интерфейса. Для начала создайте новый проект консольного приложения по имени СиstomInterfaces. Добавьте к проекту следующий абстрактный класс:namespace CustomInterfaces
{
public abstract class CloneableType
{
// Поддерживать этот "полиморфный интерфейс"
. // могут только производные типы.
// Классы в других иерархиях не имеют доступа
// к данному абстрактному члену
public abstract object Clone();
}
}
При таком определении поддерживать метод Clone()
CloneableType. Если создается новый набор классов, которые не расширяют данный базовый класс, то извлечь пользу от такого полиморфного интерфейса не удастся. К тому же вы можете вспомнить, что язык C# не поддерживает множественное наследование для классов. По этой причине, если вы хотите создать класс MiniVan, который является и Car, и CloneableType, то поступить так, как показано ниже, не удастся:// Недопустимо! Множественное наследование для классов в C# невозможно
public class MiniVan : Car, CloneableType
{
}
Несложно догадаться, что на помощь здесь приходят интерфейсные типы. После того как интерфейс определен, он может быть реализован любым классом либо структурой, в любой иерархии и внутри любого пространства имен или сборки (написанной на любом языке программирования .NET Core). Как видите, интерфейсы являются
ICloneable, определенный в пространстве имен System. В нем определен единственный метод по имени Clone():public interface ICloneable
{
object Clone();
}
Во время исследования библиотек базовых классов .NET Core вы обнаружите, что интерфейс ICloneable
System.Array, System.Data.SqlClient.SqlConnection, System.OperatingSystem, System.String и т.д.). Хотя указанные типы не имеют общего родителя (кроме System.Object), их можно обрабатывать полиморфным образом посредством интерфейсного типа ICloneable. Первым делом поместите в файл Program.cs следующий код:using System;
using CustomInterfaces;
Console.WriteLine("***** A First Look at Interfaces *****\n");
CloneableExample();