Вход/Регистрация
Полное руководство. С# 4.0
вернуться

Шилдт Герберт

Шрифт:

Один интерфейс может наследовать другой. Синтаксис наследования интерфейсов такой же, как и у классов. Когда в классе реализуется один интерфейс, наследующий другой, в нем должны быть реализованы все члены, определенные в цепочке наследо вания интерфейсов, как в приведенном ниже примере. // Пример наследования интерфейсов. using System; public interface IA { void Meth1; void Meth2; } // В базовый интерфейс включены методы Meth1 и Meth2. // а в производный интерфейс добавлен еще один метод — Meth3. public interface IB : IA { void Meth3; } // В этом классе должны быть реализованы все методы интерфейсов IA и IB. class MyClass : IB { public void Methl { Console.WriteLine("Реализовать метод Meth1."); } public void Meth2 { Console.WriteLine("Реализовать метод Meth2."); } public void Meth3 { Console.WriteLine("Реализовать метод Meth3."); } } class IFExtend { static void Main { MyClass ob = new MyClass; ob.Meth1; ob.Meth2; ob.Meth3; } }

Ради интереса попробуйте удалить реализацию метода Meth1 из класса MyClass. Это приведет к ошибке во время компиляции. Как пояснялось ранее, в любом классе, реализующем интерфейс, должны быть реализованы все методы, определенные в этом интерфейсе, в том числе и те, что наследуются из других интерфейсов. Сокрытие имен при наследовании интерфейсов

Когда один интерфейс наследует другой, то в производном интерфейсе может быть объявлен член, скрывающий член с аналогичным именем в базовом интерфейсе. Такое сокрытие имен происходит в том случае, если член в производном интерфей се объявляется таким же образом, как и в базовом интерфейсе. Но если не указать в объявлении члена производного интерфейса ключевое слово new, то компилятор вы даст соответствующее предупреждающее сообщение. Явные реализации

При реализации члена интерфейса имеется возможность указать его имя полно стью вместе с именем самого интерфейса. В этом случае получается явная реализация члена интерфейса, или просто явная реализация. Так, если объявлен интерфейс IMyIF interface IMyIF { int MyMeth(int x); }

то следующая его реализация считается вполне допустимой: class MyClass : IMyIF { int IMyIF.MyMeth(int x) { return x / 3; } }

Как видите, при реализации члена MyMeth интерфейса IMyIF указывается его полное имя, включающее в себя имя его интерфейса.

Для явной реализации интерфейсного метода могут быть две причины. Во-первых, когда интерфейсный метод реализуется с указанием его полного имени, то такой ме тод оказывается доступным не посредством объектов класса, реализующего данный интерфейс, а по интерфейсной ссылке. Следовательно, явная реализация позволяет реализовать интерфейсный метод таким образом, чтобы он не стал открытым членом класса, предоставляющего его реализацию. И во-вторых, в одном классе могут быть реализованы два интерфейса с методами, объявленными с одинаковыми именами и сигнатурами. Но неоднозначность в данном случае устраняется благодаря указанию в именах этих методов их соответствующих интерфейсов. Рассмотрим каждую из этих двух возможностей явной реализации на конкретных примерах.

В приведенном ниже примере программы демонстрируется интерфейс IEven, в котором объявляются два метода: IsEven и IsOdd. В первом из них определяет ся четность числа, а во втором — его нечетность. Интерфейс IEven затем реализуется в классе MyClass. При этом метод IsOdd реализуется явно. // Реализовать член интерфейса явно. using System; interface IEven { bool IsOdd(int x); bool IsEven(int x); } class MyClass : IEven { // Явная реализация. Обратите внимание на то, что // этот член является закрытым по умолчанию. bool IEven.IsOdd(int x) { if((x%2) != 0) return true; else return false; } // Обычная реализация, public bool IsEven(int x) { IEven о = this; // Интерфейсная ссылка на вызывающий объект. return !о.IsOdd(х); } } class Demo { static void Main { MyClass ob = new MyClass; bool result; result = ob.IsEven(4); if(result) Console.WriteLine("4 - четное число."); // result = ob.IsOdd(4); // Ошибка, член IsOdd интерфейса IEven недоступен // Но следующий код написан верно, поскольку в нем сначала создается // интерфейсная ссылка типа IEven на объект класса MyClass, а затем по // этой ссылке вызывается метод IsOdd. IEven iRef = (IEven) ob; result = iRef.IsOdd(3); if(result) Console.WriteLine("3 — нечетное число."); } }

В приведенном выше примере метод IsOdd реализуется явно, а значит, он недо ступен как открытый член класса MyClass. Напротив, он доступен только по интер фейсной ссылке. Именно поэтому он вызывается посредством переменной о ссылоч ного типа IEven в реализации метода IsEven.

Ниже приведен пример программы, в которой реализуются два интерфейса, при чем в обоих интерфейсах объявляется метод Meth. Благодаря явной реализации ис ключается неоднозначность, характерная для подобной ситуации. // Воспользоваться явной реализацией для устранения неоднозначности. using System; interface IMyIF_A { int Meth(int x); } interface IMyIF_B { int Meth(int x); } // Оба интерфейса реализуются в классе MyClass. class MyClass : IMyIF_A, IMyIF_B { // Реализовать оба метода Meth явно. int IMyIF_A.Meth(int x) { return x + x; } int IMyIF_B.Meth(int x) { return x * x; } // Вызывать метод Meth по интерфейсной ссылке. public int MethA(int x) { IMyIF_A a_ob; a_ob = this; return a_ob.Meth(x); // вызов интерфейсного метода IMyIF_A } public int MethB(int x){ IMyIF_B b_ob; b_ob = this; return b_ob.Meth(x); // вызов интерфейсного метода IMyIF_B } } class FQIFNames { static void Main { MyClass ob = new MyClass; Console.Write("Вызов метода IMyIF_A.Meth: "); Console.WriteLine(ob.MethA(3)); Console.Write("Вызов метода IMyIF_B.Meth: "); Console.WriteLine(ob.MethB(3)); } }

Вот к какому результату приводит выполнение этой программы. Вызов метода IMyIF_A.Meth: 6 Вызов метода IMyIF_B.Meth: 9

Анализируя приведенный выше пример программы, обратим прежде всего вни мание на одинаковую сигнатуру метода Meth в обоих интерфейсах, IMyIF_A и IMyIF_B. Когда оба этих интерфейса реализуются в классе MyClass, для каждого из них в отдельности это делается явно, т.е. с указанием полного имени метода Meth. А поскольку явно реализованный метод может вызываться только по интерфейсной ссылке, то в классе MyClass создаются две такие ссылки: одна — для интерфейса IMyIF_A, а другая — для интерфейса IMyIF_B. Именно по этим ссылкам происходит обращение к объектам данного класса с целью вызвать методы соответствующих ин терфейсов, благодаря чему и устраняется неоднозначность. Выбор между интерфейсом и абстрактным классом

Одна из самых больших трудностей программирования на C# состоит в правиль ном выборе между интерфейсом и абстрактным классом в тех случаях, когда требу ется описать функциональные возможности, но не реализацию. В подобных случаях рекомендуется придерживаться следующего общего правила: если какое-то понятие можно описать с точки зрения функционального назначения, не уточняя конкретные детали реализации, то следует использовать интерфейс. А если требуются некоторые детали реализации, то данное понятие следует представить абстрактным классом. Стандартные интерфейсы для среды .NET Framework

  • Читать дальше
  • 1
  • ...
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: