Почему Java не позволяет частным членам в интерфейсе?

Почему Java не разрешает закрытые члены в интерфейсе? Есть ли какая-то особая причина?

Ответ 1

Из Java Language Spec, (Контроль доступа):

"Язык программирования Java предоставляет механизмы контроля доступа, для предотвращения использования пользователями пакета или класса в зависимости от ненужные детали реализации этого пакета или класса."

Контроль доступа - это скрытие деталей реализации. Интерфейс не имеет реализации для скрытия.

Ответ 2

В Java 9 возможны частные методы в интерфейсах.

Характеристики Java 9

Команда компилятора javac рада сообщить о наличии компилятора поддержка частных методы в интерфейсах, начинающиеся с сборки 9B54 JDK.

Ответ 3

Частные интерфейсные методы будут отличаться от Java 9 как части JEP-213. Поскольку интерфейсы в Java 8 могут иметь методы по умолчанию, частные методы могут позволить нескольким методам по умолчанию использовать общий закрытый метод.

Ответ 4

Интерфейс используется для описания API, который предоставляется любым классом, реализующим интерфейс. Поскольку интерфейс из его определения не имеет состояния, нет смысла объявлять в нем члены поля.

Ответ 5

Невозможно реализовать такой интерфейс. Ответ на вопрос, который я поставил, настоятельно предполагает, что было бы невозможно (без радикального изменения правил) реализовать интерфейс с частными методами - это оставляет открытым вопрос о том, почему защищенные и закрытые частные методы не разрешены.

class OuterClass
{
     void run ( MyInterface x )
     {
           x . publicMethod ( ) ;  // why not?
           x . protectedMethod ( ) ; // why not?
           x . packagePrivateMethod ( ) ; // why not?
           x . privateMethod ( ) ; // why not?
     }

     interface MyInterface
     {
           public abstract void publicMethod ( ) ; // OK

           protected abstract void protectedMethod ( ) ; // why not?

           abstract void packagePrivateMethod ( ) ; // in interface default is public, but why not package private

           private void privateMethod ( ) ; // impossible to implement
     }

     class MyImpl implements MyInterface
     {
           public void publicMethod ( ) { } // ok

           protected void protectedMethod ( ) { } // no sweat

           void packagePrivateMethod ( ) { } // no sweat

           private void privateMethod ( ) { } // not happening
     }
}

Приведенный ниже код должен достичь желаемого результата. Несмотря на то, что все методы являются общедоступными, публичный метод является открытым. защищенный метод эффективно защищен. packagePrivateMethod эффективно packagePrivate. privateMethod является фактически конфиденциальным.

class WorkAround
{
     void run ( MyPrivateInterface x )
     {
           x . publicMethod ( ) ;  
           x . protectedMethod ( ) ; 
           x . packagePrivateMethod ( ) ; 
           x . privateMethod ( ) ; 
     }

     public interface MyPublicInterface { void publicMethod ( ) ; }

     protected interface MyProtectedInterface extends MyPublicInterface { void protectedMethod ( ) ; }

     interface MyPackagePrivateInterface extends MyProtectedInterface { void packagePrivateMethod ( ) ; }

     private interface MyPrivateInterface extends MyPackagePrivateInterface { void privateMethod ( ) ; }
}

Ответ 6

В соответствии с Java область языка программирования private members ограничена class, в которой она объявлена ​​и к ней можно получить доступ только с помощью методов этого class. Но inteface не имеет тела метода, поэтому нет использования объявления частных членов внутри interface.

Ответ 7

Как и в случае с Java 8, интерфейсы могут иметь методы по умолчанию, а с Java 9 интерфейсу будет разрешено иметь частные методы, к которым могут быть доступны только методы по умолчанию в одном интерфейсе.

Ответ 8

Это потому, что они были бы бесполезны.

Невозможно вызвать частный метод.

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

Ответ 9

частные поля не будут абсолютно бесполезны, так как другие поля и внутренние классы могут получить к ним доступ.

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

Ответ 10

Java позволяет использовать частные методы в интерфейсе Java 9. методы по умолчанию были представлены на Java 8. Возможно, что несколько методов по умолчанию хотят поделиться некоторым кодом, тогда этот код можно перенести на частный метод, не подвергая его внешнему миру. Этот bug был исправлен и начинался с JDK 9 build 54, поддержка компилятора для методов частного интерфейса была воскрешена.

public interface IData{
   default void processData(int data) {
      validate(data);
      // do some work with it
   }
   default void consumeData(int data) {
      validate(data);
      // do some work with it
   }
   private void validate(int data) {
     // validate data
   }
}

Ответ 11

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

Частные члены не согласны с этим.

Ответ 12

Члены класса, объявленные частным, не наследуются подклассы этого класса. Только участники класса, объявленные protected или public наследуются подклассами, объявленными в пакете кроме того, в котором объявлен класс.

Источник

Таким образом, у вас нет каких-либо рабочих методов в интерфейсе, который может работать с этим частным невращаемым полем. Тогда почему он должен существовать?

Ответ 13

Да, не могу этого сделать. Для всех тех, кто комментирует, почему это не должно:

Представьте, что у меня есть класс A, который использует интерфейс I. Класс B расширяет класс A, поэтому также наследует все методы интерфейса в A.

Теперь представьте, что я хочу частный метод в классе A, но хочу, чтобы он был определен по контракту для других классов (возможно, класс C, который не обязательно расширяет класс B или A).

Возможно, для метода "инициализации", который я хочу для всех классов с использованием интерфейса I. Но, очевидно, я не хочу, чтобы метод инициализации был общедоступным... поскольку его следует использовать только один раз или, как считает класс, необходимо не только потому, что вы хотите использовать его волей-неволей.

Единственное решение - это обходное решение или просто принудительное использование метода init в самих классах без интерфейса.

Я понимаю причину не слишком, конечно, но все же, она может пригодиться иногда. Очевидно, Oracle соглашается с тем, что они разрешают методы частного интерфейса в JDK 9.

То, что я сделал, для меня в любом случае, содержало простую логическую переменную, таким образом метод интерфейса (который должен быть закрытым) можно пометить как true (initialized = true) после установки один раз. Затем при вызове снова метод просто ничего не делает. Таким образом, метод интерфейса может быть реализован как общедоступный, но поскольку конструктор (моего класса) сначала вызывает этот метод, он устанавливает переменную в true и поэтому ее нельзя вызвать снова.

В противном случае вам придется попробовать другое обходное решение, если вы хотите, чтобы внутренняя работа этого класса использовала его... возможно, сам метод устанавливает флаг вкл и выкл, когда он его использует. Когда флаг является ложным, метод ничего не делает (это было бы, когда кто-то вызывал его извне класса). Тем не менее, когда классы, связанные с его методами, называют это, они быстро устанавливают флаг в true, затем вызывают метод, а затем устанавливают флаг в false??

В конце концов, немой. Вероятно, теперь просто лучше просто поместить частный класс в сам класс и полностью вырезать интерфейс.