私有接口方法,示例用例?

Posted

技术标签:

【中文标题】私有接口方法,示例用例?【英文标题】: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() 默认方法中。这会导致代码重复,这是不可取的。

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

感谢您的回答!

【问题讨论】:

【参考方案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 版本。

【讨论】:

以上是关于私有接口方法,示例用例?的主要内容,如果未能解决你的问题,请参考以下文章

C#:使用实现私有接口的对象参数测试方法

使用 FakeItEasy 的私有方法和属性的单元测试用例 [重复]

如何使用junit和mockito为私有void方法编写测试用例[重复]

Java 默认接口方法具体用例

私有接口与私有方法 - 目标 c

接口私有方法使用