Почему Java разрешает интерфейсам иметь статические поля только для чтения, а интерфейсы .NET - нет? - PullRequest
5 голосов
/ 01 августа 2010

Я столкнулся с примером кода на Java, и это вызвало у меня вопрос.

Java Пример кода:

...
public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
    void printf(String format, Object... args);
}

public static void main(String[] args) throws IOException {
    CLibrary.INSTANCE.printf("Hello, World\n");
}

Но в C # мы не можем написать так:

public interface IMyInterface {
    static readonly int staticInt = 5;                          // compile error
    static readonly SomeClass staticInstance = new SomeClass(); // compile error
}

В чем разница между этими двумя языками / средами?

Какая политика разработки разрешает java иметь поля const в интерфейсе или что мешает.NET от этого?

Ответы [ 6 ]

6 голосов
/ 01 августа 2010

Использование интерфейсов для хранения констант обычно в наши дни не одобряется и в Java. (Я бы сказал, что хранение не-постоянных времени компиляции полей, подобных вашему примеру, еще более неодобрительно.)

По сути, это странно с идеей интерфейса: контракт, который будет поддерживать реализация. Реализация не собирается предоставлять поле, так что он там делает?

Я подозреваю, что команда C # решила, что она достаточно расходится с концепцией интерфейсов, чтобы не включать ее в язык. Я не знаю, просто ли это ограничение C # или CLR тоже. Например, я знаю, что CLR позволяет интерфейсам объявлять вложенные типы, но C # в настоящее время не позволяет этого.

2 голосов
/ 01 августа 2010

В C #:

Интерфейсы состоят из методов, свойства, события, индексаторы или любые Сочетание этих четырех членов типы. Интерфейс не может содержать константы, поля, операторы, экземпляр конструкторы, деструкторы или типы. Он не может содержать статические члены. Члены интерфейсов автоматически общественности, и они не могут включать модификаторы доступа.

На Java:

Каждая декларация поля в теле интерфейс неявно публичный, статический и окончательный.

Каждое поле в теле интерфейс должен иметь инициализацию выражение, которое не должно быть постоянное выражение. Переменная инициализатор оценивается и задание выполняется ровно один раз, когда интерфейс инициализирован.

0 голосов
/ 01 августа 2010

Как и большинство вопросов этой формы, вопрос в основном бессмысленный. Не то чтобы дизайнеры Java и C # встречались по этому поводу. Исторически Java была на первом месте, так что вам действительно нужно было спросить разработчиков C #, не то чтобы этот вопрос также имел для них смысл. Это просто, как они видели это в то время.

0 голосов
/ 01 августа 2010

Я полагаю, что язык описания интерфейсов Microsoft COM не позволяет этого. Так что это просто адаптация к среде Windows, во многом как префикс имен интерфейсов с I.

0 голосов
/ 01 августа 2010

Я думаю, странно, что Java решила это разрешить.

Интерфейс - это контракт для роли.То есть это спецификация, которую должны реализовать все объекты, чтобы их можно было рассматривать в качестве подходящих / заменяемых кандидатов на эту роль.Он должен содержать сообщений / методов, на которые отвечает Роль, и уведомлений, которые она вызывает для заинтересованных слушателей .

Поля - это детали реализации (а ваш пример содержит фактическую реализацию, диктующую возвращаемое значение).для поля INSTANCE тоже) и не входят в контракт.Если вы хотите отобразить это на C #, вам, вероятно, следует переместить его в абстрактный базовый класс , который позволяет указывать реализацию по умолчанию в дополнение к указанию некоторых членов, которые также должны реализовывать производные классы.

0 голосов
/ 01 августа 2010

В Java все поля в интерфейсе неявно являются статическими и конечными.Но это считается плохой практикой.Чтобы цитировать Джошуа Блоха из Effective Java:

Постоянный шаблон интерфейса - это плохое использование интерфейсов.То, что класс использует некоторые константы внутри, является деталью реализации.Реализация постоянного интерфейса вызывает утечку этой детали реализации в экспортируемый API класса.Для пользователей класса не имеет значения, что класс реализует постоянный интерфейс.На самом деле, это может даже запутать их.Хуже того, он представляет собой обязательство: если в будущем выпуске класс будет изменен так, что ему больше не нужно будет использовать константы, он все равно должен реализовать интерфейс для обеспечения двоичной совместимости.Если нефинальный класс реализует постоянный интерфейс, все его подклассы будут иметь свои пространства имен, загрязненные константами в интерфейсе.

Что касается того, почему это считается плохой практикой, я думаю, что класс, реализующий интерфейсс константными полями предоставляет их в интерфейсе внешнему коду, который использует этот класс, что в большинстве случаев не то, что требуется.

...