Язык программирования C#9 и платформа .NET5. Страница 165
using System;using CustomInterfaces;Console.WriteLine("***** A First Look at Interfaces *****\n");CloneableExample();Далее добавьте к операторам верхнего уровня показанную ниже локальную функцию по имени
CloneMe()ICloneablestatic void CloneableExample(){ // Все эти классы поддерживают интерфейс ICloneable. string myStr = "Hello"; OperatingSystem unixOS = new OperatingSystem(PlatformID.Unix, new Version()); // Следовательно, все они могут быть переданы методу, // принимающему параметр типа ICloneable. CloneMe(myStr); CloneMe(unixOS); static void CloneMe(ICloneable c) { // Клонировать то, что получено, и вывести имя. object theClone = c.Clone(); Console.WriteLine("Your clone is a: {0}", theClone.GetType().Name); }}После запуска приложения в окне консоли выводится имя каждого класса, полученное с помощью метода
GetType()System.Object***** A First Look at Interfaces *****Your clone is a: StringYour clone is a: OperatingSystemЕще одно ограничение абстрактных базовых классов связано с тем, что каждый производный тип должен предоставлять реализацию для всего набора абстрактных членов. Чтобы увидеть, в чем заключается проблема, вспомним иерархию фигур, которая была определена в главе 6. Предположим, что в базовом классе
ShapeGetNumberOfPoints()namespace CustomInterfaces{ abstract class Shape { ... // Теперь этот метод обязан поддерживать каждый производный класс! public abstract byte GetNumberOfPoints(); }}Очевидно, что единственным классом, который в принципе имеет вершины, будет
HexagonCircleHexagonThreeDCircleGetNumberOfPoints()HexagonCircleThreeDCircleНа заметку! Изменения интерфейсов в версии C# 8 являются, по всей видимости, наиболее существенными изменениями существующего языка за весь обозримый период. Как было ранее описано, новые возможности интерфейсов значительно приближают их функциональность к функциональности абстрактных классов с добавочной способностью классов реализовывать множество интерфейсов. В этой области рекомендуется проявлять надлежащую осторожность и здравый смысл. Один лишь факт, что вы можете что-то делать, вовсе не означает, что вы обязаны поступать так.
Определение специальных интерфейсов
Теперь, когда вы лучше понимаете общую роль интерфейсных типов, давайте рассмотрим пример определения и реализации специальных интерфейсов. Скопируйте файлы
Shape.csHexagon.csCircle.csThreeDCircle.csShapesCustomInterfасеIPointy.csНа синтаксическом уровне интерфейс определяется с использованием ключевого слова
interfaceSystem.Objectprivateinternalprotectedstaticnamespace CustomInterfaces{ // Этот интерфейс определяет поведение "наличия вершин". public interface IPointy { // Неявно открытый и абстрактный. byte GetNumberOfPoints(); }}