【问题标题】:Private interface methods, example use-case?私有接口方法,示例用例?
【发布时间】:2015-05-16 10:36:35
【问题描述】:

“对于接口中的私有方法的支持曾一度考虑包含在 Java SE 8 中,作为增加对 Lambda 表达式支持的努力的一部分,但为了更好地专注于 Java SE 8 的更高优先级任务而被撤回。它是现在提议支持私有接口方法,从而使接口的非抽象方法能够在它们之间共享代码。”

http://openjdk.java.net/jeps/213 的规范如此说,并在错误报告中说https://bugs.openjdk.java.net/browse/JDK-8071453

但我真的想不出任何必要的用例,即使上面给出了简短的解释。我可以问一个“私有接口方法”在代码方面有用的例子吗?

编辑:所以答案是,由于 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() 默认方法中。这会导致代码重复,这是不可取的。

因此,这会导致重构出现问题,为了消除这种代码重复,允许使用私有默认方法。

感谢您的回答!

【问题讨论】:

    标签: java interface private java-9


    【解决方案1】:

    接口现在可以有default methods。添加这些是为了可以将新方法添加到接口中,而不会破坏实现这些更改的接口的所有类。

    如果两个默认方法需要共享代码,私有接口方法将允许它们这样做,但不会通过接口公开该私有方法及其所有“实现细节”。

    【讨论】:

    • 这些方法基本上是语法糖来调用静态方法,否则这些方法可能是包私有的吗?
    • 不,因为您可以在实现中将它们作为实例方法覆盖,如果您使用静态方法,这是您无法做到的。
    • 这样的压倒一切如何工作?覆盖可以访问什么,什么可以访问覆盖?
    • 我现在意识到您可能在谈论私有接口方法,而我假设我们在谈论默认方法:) 我不知道私有方法将如何实现,但我不知道不要认为他们会使用静态方法,因为您经常希望使用其他实例方法来计算结果。也许这值得提出自己的问题......
    • 那么,为什么不使用抽象类呢?想说:对于一个界面来说,它们不是太多东西吗?我将接口视为合同,而不是实现,并且为了 lambdas 我接受默认方法,但我认为这已经失控......他们应该允许多重继承并停止它。
    【解决方案2】:

    为什么不简单(简单地 = 使用 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;
     }
    }
    

    【讨论】:

    • 好技巧,可能是因为它不太方便,但它是一个好技巧!
    • 我在“年龄”中广泛使用此类助手。从我的 POV 来看,编程语言以这种方式扩展来实现这样的目的有点奇怪,增加了不必要的复杂性。
    • 私有静态类不能在这里用我的 Eclipse 编译
    • @maxim_ge 我不知道你的编译器怎么允许你使用这样的声明!!!但它不能与我的 Java 8u131 一起编译,除非我对 Helper 类使用公共或包级别!
    • @maxim_ge 仅当您从类声明中删除 private 和 static 关键字时才会编译。即使这样,这也与接口中的私有方法不同。您仍然可以通过键入 MyInterface.Helper 访问 Helper 类。接口中的私有方法是完全隐藏的,并且无法从接口外部访问。
    【解决方案3】:

    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 版本。

    【讨论】:

      猜你喜欢
      • 2012-03-25
      • 1970-01-01
      • 2014-06-02
      • 2018-06-21
      • 2020-05-29
      • 2011-03-10
      • 1970-01-01
      • 2012-01-04
      • 2018-11-16
      相关资源
      最近更新 更多