Книга: C# 4.0: полное руководство
Явные реализации
Явные реализации
При реализации члена интерфейса имеется возможность указать его имя полностью вместе с именем самого интерфейса. В этом случае получается явная реализация члена интерфейса, или просто явная реализация. Так, если объявлен интерфейс 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(x);
}
}
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
. Именно по этим ссылкам происходит обращение к объектам данного класса с целью вызвать методы соответствующих интерфейсов, благодаря чему и устраняется неоднозначность.
- Возможности, планируемые к реализации в следующих версиях
- 1.9 Сложности практической реализации
- 2.7 Сложности практической реализации
- 3.8 Сложности практической реализации
- 4.10 Сложности практической реализации
- 5.9 Сложности практической реализации
- 6.7 Сложности практической реализации
- 7.10 Сложности практической реализации
- 8.3 Сложности практической реализации
- 9.5 Сложности практической реализации
- 10.6 Сложности практической реализации
- Instagram как платформа для реализации.