Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 只有一个实现的接口_Java_Oop_Interface - Fatal编程技术网

Java 只有一个实现的接口

Java 只有一个实现的接口,java,oop,interface,Java,Oop,Interface,在使用jmock时,如果设置类冒名顶替器,则可以模拟具体的类。我注意到类冒名顶替器在遗留包中,所以我真的不想使用它(特别是因为使用IDE中的重构工具提取接口非常容易)。我也不喜欢有具体类的实例变量 但是,在提取接口时,我注意到代码库中出现了一种模式。很多时候,一个接口只有一个实现具体类。我更喜欢尽可能地使用接口,但拥有所有这些额外文件似乎真的很冗长。此外,每次我想向类添加新方法时,更新接口和更新实现者都有点繁琐 这仅仅是你为适当的抽象所付出的代价,还是有一种更好的方法我没有想到?即使接口中只有g

在使用jmock时,如果设置类冒名顶替器,则可以模拟具体的类。我注意到类冒名顶替器在遗留包中,所以我真的不想使用它(特别是因为使用IDE中的重构工具提取接口非常容易)。我也不喜欢有具体类的实例变量

但是,在提取接口时,我注意到代码库中出现了一种模式。很多时候,一个接口只有一个实现具体类。我更喜欢尽可能地使用接口,但拥有所有这些额外文件似乎真的很冗长。此外,每次我想向类添加新方法时,更新接口和更新实现者都有点繁琐


这仅仅是你为适当的抽象所付出的代价,还是有一种更好的方法我没有想到?即使接口中只有getter/setter,所有类都应该实现一个接口吗?

如果接口冗长乏味,无论理论上有什么优势,都是不好的风格

如果使用您的工具很容易提取接口,为什么现在就这么做?为什么不在它真正有目的的时候去做呢。我看到太多的代码是为了未来而设计的,而不是为了解决眼前的问题


当然,所有关于这些问题的辩论都只是意见。没有事实可供发现。

如果接口只是getter和setter,那么听起来它更多地与数据有关,而不是与行为有关,而且听起来不像是我要嘲笑的那种东西。我很乐意在其他类的测试中直接使用简单的生产代码。我只为提供服务的类注入依赖项

我感觉到你的痛苦,但就我个人而言,我仍然编写接口,即使目前只有一个生产实现。很多时候,我会发现在模拟一段时间后,我也编写了存根或伪实现。除非您真的对测试调用者和服务之间的交互感兴趣,否则赝品最终可能会变得更易于使用(导致更清晰的测试)


这还意味着,当有人想要查看某个特定依赖项提供的方法时,他们可以只查看接口,而不涉及任何实现。

如果有额外的接口会冒犯您,您可以(手动)创建模拟对象,作为所模拟类的子类

如果一个类仅仅由(简单的)getter和setter组成,那么嘲笑它几乎没有任何意义。使用真实的东西。

你提到“适当的抽象”。嗯,只有当接口对多个类有意义时才合适。特别是考虑到您是从具体的类中提取接口,您可能最终在接口中得到了不应该存在的方法。当然,如果接口本身首先存在是有意义的话

我要指出的最后一点是,您的接口似乎不是特别稳定。您似乎在暗示向接口添加方法对您来说是司空见惯的。当类的契约(即其接口)如此易变时,我会质疑类的抽象


总而言之,我不认为立即为所有内容提供接口就构成了适当的抽象。相反,从设计的角度来看,先等待类的公共接口稳定下来,然后考虑适当的抽象(即不只是点击IDE中的
“提取接口…”
按钮)要好得多。另外,一个类可能会抽象成几个不相关的接口,而不是单个接口。

如果您的接口主要是属性,那么所有实现类都可能是相关的,也许抽象类更适合您的需要。然后你就可以避免一些陈词滥调了。抽象类的主要功能仍然可以通过接口进一步抽象

interface IRunner {
      void run();
      int doOtherThing();
}

abstract class Thing implements IRunner {

    //this is class-specific
    abstract void run();
    //this is common to all 'Things'
    int doOtherThing() { return 0; }

    //as are these properties
    public int getProp() {...}
    public void setProp(int val) {...}

}

public class Goo extends Thing {
      public void run() {
         int i = getProp() + doOtherThing();
         makeMagicGoo(i);
      }

}

有一个关键用例,即使您只编写了一个对象的实现,为对象生成接口也是至关重要的:您希望能够为类的实例生成JDK代理(例如,如果您正在执行Spring AOP,这很有用)。可以使用cglib之类的工具为任意对象构建代理,但要复杂得多;相比之下,JDK代理很简单


我也有点担心你的IDE并没有给你带来应有的帮助。我发现使用我的(Eclipse),只要在实现中用
@Override
标记方法并选择正确的自动修复选项,就可以在接口中创建方法。(这并不是说它会选择正确的方法解释,但这是你的工作。)

我所说的一些一般要点:

  • 测试中的模拟是替代实现。因此,即使产品代码中只有一个实现,代码库中也会有多个实现
  • 比起getter和setter,更喜欢构造函数注入。这也将使不可变对象更自然
  • 接口描述了一个行为的契约,并且以一种接口的用户不需要知道实现细节的方式进行描述
  • 不要为与这些事情无关的事情制作接口:抽象掉实现细节;多个替代实现;可模仿性;行为
  • 与很少有大型互联部件的设计相比,更喜欢具有许多小型组成部件的设计
  • 如果某个东西很难测试或模拟,那么尝试将其分解为具有更简单API的较小部分,然后组合这些部分
  • 给事物精确的名称,不仅要注意代码的重复,还要注意结构和名称的重复
  • 避免实现继承-更喜欢组合。接口继承很难被误用,而且经常会失效