Методы частного интерфейса, пример использования?

«Поддержка закрытых методов в интерфейсах кратко рассматривалась для включения в Java SE 8 в рамках усилий по добавлению поддержки лямбда-выражений, но была отозвана, чтобы лучше сосредоточиться на задачах с более высоким приоритетом для Java SE 8. Теперь предлагается, чтобы должна быть предпринята поддержка методов частного интерфейса, что позволит неабстрактным методам интерфейса совместно использовать код между собой».

Так говорит спецификация для http://openjdk.java.net/jeps/213 и говорится в отчет об ошибке https://bugs.openjdk.java.net/browse/JDK-8071453 .

Но я не могу придумать ни одного варианта использования, где это необходимо, даже с учетом приведенного выше краткого объяснения. Могу ли я попросить пример, когда «методы частного интерфейса» полезны с точки зрения кода?

EDIT: Таким образом, ответ заключается в том, что из-за того, как реализации по умолчанию были добавлены к интерфейсам в Java 8, могут быть случаи, когда реализации по умолчанию используют одну и ту же кодовую базу.

Например,

public interface MyInterface {
     default void initializeMyClass(MyClass myClass, Params params) {
         //do magical things in 100 lines of code to initialize myClass for example
     }

     default MyClass createMyClass(Params params) {
         MyClass myClass = new MyClass();
         initializeMyClass(myClass, params);
         return myClass;
     }

     default MyClass createMyClass() {
         MyClass myClass = new MyClass();
         initializeMyClass(myClass, null);
         return myClass;
     }
}

Глупый пример, я знаю. Но допустим, что мы хотим использовать initializeMyClass(MyClass, Params) в обоих методах. Однако, если мы сделаем это так (метод по умолчанию), то initializeMyClass(MyClass, Params) будет частью публичного интерфейса! Чтобы этого не произошло, мы можем хранить код всего initializeMyClass(MyClass, Params) только внутри createMyClass() методов по умолчанию. Что приводит к дублированию кода, что нежелательно.

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

Спасибо за ответы!


person EpicPandaForce    schedule 13.03.2015    source источник


Ответы (3)


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

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

person mk.    schedule 13.03.2015
comment
Являются ли такие методы в основном синтаксическим сахаром для вызова статических методов, которые в противном случае могли бы быть приватными для пакета? - person supercat; 13.03.2015
comment
Нет, потому что вы можете переопределить их как методы экземпляра в своей реализации, чего вы не сможете сделать, если используете статический метод. - person mk.; 13.03.2015
comment
Как будет работать такое переопределение? К чему может получить доступ переопределение и что может получить доступ к переопределению? - person supercat; 13.03.2015
comment
Он ведет себя точно так же, как определение любого другого метода интерфейса (но поскольку там уже есть какой-то код, мы называем его переопределением/переопределением). Если вы переопределяете метод по умолчанию, вы можете сделать вид, что реализовали метод абстрактного интерфейса. - person mk.; 13.03.2015
comment
Насколько я понимаю, Java требует, чтобы методы, реализующие интерфейсы, были закрытыми. Сможет ли код, который хочет переопределить частный метод интерфейса, сделать это, не делая переопределение общедоступным? Будет ли реализация интерфейса иметь доступ к любому из закрытых членов интерфейса [даже если реализующий класс теоретически может копировать/вставлять члены закрытого интерфейса для собственного использования, что может привести к поломке, если члены позже изменятся в интерфейсе, но не в собственная копия класса). - person supercat; 13.03.2015
comment
Теперь я понимаю, что вы могли говорить о частных методах интерфейса, в то время как я предполагал, что мы говорим о методах по умолчанию :) Я не знаю, как будут реализованы частные методы, но я не думаю, что они будут использовать статические методы , так как вы часто захотите использовать другие методы экземпляра для вычисления результата. Может быть, это стоит сделать отдельный вопрос ... - person mk.; 14.03.2015
comment
О, я вижу. Учитывая, что это private, я думаю, что его нельзя переопределить каким-либо образом, поскольку его видит только интерфейс, но его можно использовать для реализации в методах по умолчанию, не загрязняя интерфейс внутренней логикой. Имеет смысл, спасибо! - person EpicPandaForce; 14.03.2015
comment
Так почему бы тогда не использовать абстрактный класс? Хотите сказать: это не слишком много для интерфейса? Я вижу интерфейс как контракт, а не как реализацию, и я принимаю методы по умолчанию ради лямбда-выражений, но я думаю, что это выходит из-под контроля... Они должны разрешить множественное наследование и остановить его. - person inigoD; 25.04.2017
comment
Вот пример варианта использования, который я пытался создать для сортировки вопросов SO. - person Naman; 14.09.2017

Почему бы не просто (просто = используя Java8):

PS: из-за частного помощника в Java это невозможно

public interface MyInterface {
 private static class Helper{
     static initializeMyClass(MyClass myClass, Params params){
         //do magical things in 100 lines of code to initialize myClass for example
     }
 }

 default MyClass createMyClass(Params params) {
     MyClass myClass = new MyClass();
     Helper.initializeMyClass(myClass, params);
     return myClass;
 }

 default MyClass createMyClass() {
     MyClass myClass = new MyClass();
     Helper.initializeMyClass(myClass, null);
     return myClass;
 }
}
person maxim_ge    schedule 02.06.2017
comment
Хороший трюк, возможно, потому что он немного менее удобен, но это хороший трюк! - person EpicPandaForce; 02.06.2017
comment
Я использую такие помощники широко на протяжении веков. Немного странно, что язык программирования расширен таким образом для такой цели, дополнительного уровня ненужного усложнения, с моей точки зрения. - person maxim_ge; 05.06.2017
comment
частный статический класс не компилируется с моим затмением здесь - person Werner Thumann; 02.07.2017
comment
@maxim_ge Я не знаю, как ваш компилятор позволяет вам использовать такое объявление!!! но он не компилируется с моей Java 8u131, если я не использую общедоступный уровень или уровень пакета для класса Helper! - person O.Badr; 07.08.2017
comment
@maxim_ge Это скомпилируется, только если вы удалите ключевые слова private и static из объявления класса. Даже тогда это не то же самое, что частные методы в интерфейсах. Вы по-прежнему можете попасть в класс Helper, набрав MyInterface.Helper. Приватные методы в интерфейсах полностью скрыты и недоступны снаружи интерфейса. - person gajos; 31.08.2017
comment
@WernerThuman и другие - вы правы, добавлена ​​поправка. - person maxim_ge; 05.09.2017

Java 9 позволяет объявлять закрытый метод внутри интерфейса. Вот пример этого.

interface myinterface {
    default void m1(String msg){
        msg+=" from m1";
        printMessage(msg);
    }
    default void m2(String msg){
        msg+=" from m2";
        printMessage(msg);
    }
    private void printMessage(String msg){
        System.out.println(msg);
    }
}
public class privatemethods implements myinterface {
    public void printInterface(){
        m1("Hello world");
        m2("new world");
    }
    public static void main(String[] args){
        privatemethods s = new privatemethods();
        s.printInterface();
    }
}

Для этого вам необходимо обновить jdk до версии 1.9.

person Dhiral Kaniya    schedule 04.02.2018