Вопрос по java – Почему Java не допускает закрытые члены в интерфейсе?

73

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

Что будут делать такие частные члены? Mankarse
Этот вопрос не так глуп, как звучит, поскольку он также влияет (или, скорее, не обеспечивает большого контроля) на контроль доступа реализующих классов ... user166390
Обратите внимание, что защищенные и закрытые для пакета члены также не допускаются: все члены интерфейса неявно общедоступны. Arend v. Reinersdorff
@pst я написал обходной путь в конце моего ответа -stackoverflow.com/a/10169894/348975, Это касается ваших проблем? emory

Ваш Ответ

13   ответов
7

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

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 ( ) ; }
}
3

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

   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
   }
}
3

Не было бы способа вызвать закрытый метод.

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

Рассмотрим стандартные методы java 8. Интерфейс I имеет стандартные методы A и B с большим количеством общего кода. Для рефакторинга этого вам понадобится метод C, который будет содержать только общий код и вызываться A и B. В Java 8 это будет метод по умолчанию, доступный для всех разработчиков интерфейса. в Java 9 C может быть закрытым методом, видимым только для методов по умолчанию в I.
Я не согласен с "не было бы способа вызвать закрытый метод". С внутренними классами был бы способ -stackoverflow.com/a/10169894/348975
13

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

11

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

Полезно знать о возможностях интерфейса Java-9.
9

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

В java land член - это поле, метод, конструктор или класс.
6

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

0

subclasses of that class. Only members of a class that are declared protected or public are inherited by subclasses declared in a package other than the one in which the class is declared.

Источник

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

2

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

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

Извините за могилу здесь :( Как этоdocs.oracle.com/javase/7/docs/api/java/io/Serializable.html работать в этом случае? Могут ли люди это реализовать, а затем перезаписать методы readObject и writeObject? Я уверен, что что-то упустил
0

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

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

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

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

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

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

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

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

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

81

Спецификация языка Java, (Контроль доступа):

"The Java programming language provides mechanisms for access control, to prevent the users of a package or class from depending on unnecessary details of the implementation of that package or class."

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

Java 9 допускает закрытые методы в интерфейсе. Это логично после добавления методов по умолчанию, Ref:bugs.openjdk.java.net/browse/JDK-8071453
«Это очень неправильно», как всегда, зависит от контекста.
Это не так плохо, как кажется. Закрытые методы в интерфейсе могут быть доступны только по умолчанию в том же интерфейсе. Одно из преимуществ состоит в том, чтобы помочь разбить реализацию методов по умолчанию на значимые меньшие функции без нарушения инкапсуляции.
Поскольку мы можем поместить вложенные классы в интерфейс, мы можем поместить реализацию в интерфейс. Это очень неправильно, но мы можем.
1

доступа к классу с помощью определенных методов, где вам не нужно видеть внутренности этого класса.

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

39

Спецификации Java 9

The javac compiler team is pleased announce the availability of compiler support for private methods in interfaces beginning with 9 b54 build of JDK.

@ SebiSebi, момент, когда вы понимаете, что Java - это живой язык.

Похожие вопросы