Интерфейс - это контракт. Он говорит: «Я могу сделать это». Какой смысл кому-то вручать вам экземпляр IInterface
, в котором вы не можете использовать некоторые методы этого контракта, потому что они были помечены как не публичные?
Это обоснование для разработки языка таким способом. Спецификация для этого находится в §13.2 спецификации языка:
Все члены интерфейса неявно имеют открытый доступ. Это ошибка времени компиляции для объявлений членов интерфейса, чтобы включить любые модификаторы. В частности, элементы интерфейса не могут быть объявлены с модификаторами abstract
, public
, protected
, internal
, private,
virtual
, override
или static
.
Что касается вашего кода, это пример явной реализации интерфейса . Это наиболее полезно, когда класс или структура реализуют два интерфейса, каждый из которых имеет член с одинаковой сигнатурой. Например, IEnumerable
и IEnumerable<T>
определяют метод GetEnumerator
, не принимающий параметров.
public interface IEnumerable {
IEnumerator GetEnumerator();
}
public interface IEnumerable<T> : IEnumerable {
IEnumerator<T> GetEnumerator();
}
Обратите внимание, что согласно приведенным выше определениям любой класс, который реализует IEnumerable<T>
, должен также реализовывать IEnumerable
. Имейте в виду, что тип возвращаемого значения не является частью подписи, и поэтому у нас есть конфликт с IEnumerable.GetEnumerator
и IEnumerable<T>.GetEnumerator
. Вот что должна решить явная реализация интерфейса:
class X<T> : IEnumerable<T> {
List<T> _list = new List<T>();
public IEnumerator<T> GetEnumerator() {
return _list.GetEnumerator();
}
IEnumerator GetEnumerator() {
return GetEnumerator(); // invokes IEnumerable<T>.GetEnumerator
}
}
Члены, которые являются явными реализациями интерфейса, видны только через экземпляр интерфейса. Таким образом:
X<int> x = new X<int>();
var e1 = x.GetEnumerator(); // invokes IEnumerable<int>.GetEnumerator
// IEnumerable.GetEnumerator is not visible
IEnumerable y = x;
var e2 = y.GetEnumerator(); // invokes IEnumerable.GetEnumerator
Таким образом, в вашем коде
X ob = new Y();
ob.add(1, 2); // X.add is visible through interface
Y y = new Y();
y.add(1, 2); // compile-time error, X.add is not visible
Оба метода не требуют модификаторов, но когда я не использую интерфейс, как X.add () выше, мне нужно сделать реализацию общедоступной. Почему?
Хорошо, не совсем понятно, о чем вы здесь спрашиваете. Модификаторы доступа не допускаются для явных реализаций интерфейса. Это 13.4:
Это ошибка времени компиляции для явной реализации элемента интерфейса, которая включает модификаторы доступа, и это ошибка времени компиляции, чтобы включить модификаторы abstract
, virtual
, override
или static
.
Если реализация интерфейса не помечена как явная реализация интерфейса, то она должна иметь модификатор доступа public
. Это 13.4.4 (Отображение интерфейса):
Отображение интерфейса для класса или структуры C
находит реализацию для каждого члена каждого интерфейса, указанного в списке базовых классов C
. Реализация конкретного элемента интерфейса I.M
, где I
является интерфейсом, в котором объявлен элемент M
, определяется путем изучения каждого класса или структуры S
, начиная с C
и повторяя для каждого последующего базовый класс C
, пока не будет найден матч
Если S
содержит объявление явной реализации элемента интерфейса, которая соответствует I
и M
, то этот элемент является реализацией I.M
В противном случае, если S
содержит объявление нестатического открытого члена, совпадающего с M
, то этот элемент является реализацией I.M
.
Ошибка времени компиляции происходит, если реализации не могут быть найдены для всех членов всех интерфейсов, указанных в списке базовых классов C
.
Итак, вкратце, компилятор сначала ищет явную реализацию интерфейса. Если он не может найти его, он ищет нестатический, открытый член с той же сигнатурой, что и у реализуемого метода M
. Если это не может найти один, происходит ошибка времени компиляции. Так что правила таковы. Для реализации члена интерфейса I.M
:
Если вы реализуете I.M
явно, то синтаксис будет
return-type I.M(parameter-list)
В противном случае синтаксис будет
public return-type M(parameter-list)
Таким образом, с
interface IAdd {
int Add(int x, int y)
}
Мы можем реализовать явно:
class Explicit : IAdd {
int IAdd.Add(int x, int y) { return x + y; }
}
или нет:
class NotExplicit : IAdd {
public int Add(int x, int y) { return x + y; }
}
Разница в том, что Explicit.Add
не отображается, если только экземпляры Explicit
не набраны как IAdd
:
IAdd explicitInterface = new Explicit();
explicitInterface.Add(2, 2);
Explicit explicit = new Explicit();
explicit.Add(2, 2); // compile-time error
* * В то время как одна тысяча сто двадцать пять * * тысяча сто двадцать шесть
IAdd notExplicitInterface = new NotExplicit();
notExplicitInterface.Add(2, 2);
NotExplicit notExplicit = new NotExplicit();
notExplicit.Add(2, 2); // okay, NOT a compile-time error as above
Это помогает?