【问题标题】:The purpose of interfaces continued接口的用途(续)
【发布时间】:2010-10-29 14:10:11
【问题描述】:

好的,所以我认为接口是一种强制对象实现一定数量功能的方法,而不必使用继承。有点像合同。我半明白他们的意思。

但如果你在界面中只有:

 public interface animal{
  void eat(object food);
}

而且它本身没有实现,那么无论谁使用你的接口,每次都必须从头开始编写它。

如果您要创建多个类都实现了这些功能,而实现只是略有不同,这将是一项艰巨的工作。

感谢任何帮助我解决这个问题,因为我知道这非常重要。

【问题讨论】:

  • 对不起,我糟糕的“错别字”,Carl 只是点击了按钮,没有真正仔细阅读。很多在我的脑海里似乎。当你看到错误时,令人畏惧的东西。

标签: java oop interface


【解决方案1】:

接口是在 Java 中创建多重继承的唯一方法。

假设您创建了一个类Animal。包括人类在内的所有动物都扩展了这一点。而且这些动物中的每一种都继承了常见的方法,例如进食、呼吸等。

但是现在假设你有一个MathProblem 类。 并且您希望某些类可以通过将问题传递给solve(MathProblem problem) 方法来解决该问题。 你知道HumanComputer 可能会解决数学问题。所以他们都需要能够解决这个问题。您也许可以让 Computer 扩展一些具有该方法的 MathSolver 类,但 Human 已经扩展了 Animal,并且不能扩展其他任何东西。所以更好的方法是让 MathSolver 成为一个接口,同时让 HumanComputer 和任何其他需要解决问题的类都实现它。

还要注意HumanComputer 可能以完全不同的方式解决问题,因为它们的对象不同。这就是接口最适合的地方。定义跨越多个继承层次结构的某些功能,并且可以具有非常不同的实现,但都可以传递给接受其中任何一个的方法。想想Comparable 接口;它不是某一类对象所具有的东西,所有类型的东西都可以比较,而且通常以非常不同的方式进行比较。但是您总是可以对 Comparable 对象中的 List 调用 sort,因为您知道它们有一定的顺序,无论它们是 NumbersAnimalsComputers 还是其他任何东西(只要它们实现Comparable 并定义它们的顺序)。

【讨论】:

  • +1 - 我认为重要的是要补充一点,继承有两个目的:(1)允许使用继承类对象代替基类对象,以及(2)允许继承-class 对象以使用基类行为。接口对第二个目的没有任何用处,但对第一个目的很有帮助。
【解决方案2】:

Prefer Composition over Inheritance. 这样,您可以在一个类中实现(比如说)eat(),该类作为数据成员并入您的所有动物中。编写一次,重复使用,但不会将一种功能显式绑定到另一种功能。

如果您有两种(或十种)不同的饮食方式,您可以根据需要更换它们。

【讨论】:

  • 虽然在这种特殊情况下组合似乎是避免代码重复的最佳方法,但这个答案往往让人认为接口在 Java 中是无用的。不要忘记还有另一个设计原则是“程序到接口,而不是具体类”。因此,Java 中的接口绝对是几乎无处不在的理解和使用的东西。
  • 好点。我刚刚编辑添加了“交换”位,我认为可以解决它。谢谢。
【解决方案3】:

您混淆了接口和继承。它们是不同的概念,可以相互补充。如果所有的eat方法只是略有不同,那么您可以创建一个包含公共代码的基类,并将通过添加不同部分的覆盖方法从子类中调用。基类仍然可以实现接口。希望清楚。

【讨论】:

    【解决方案4】:

    是的,您每次都需要实现它,但您可以每次都以不同的方式实现它,任何调用它的类都不需要担心它是如何实现的。

    例如,如果您有一个 Zoo 对象,其中包含一群动物(new Tiger()、Lion()、Bear()),那么您的动物园可以为某个集合 a.eat() 中的每个 Animal a 做将工作。动物园不在乎三种不同类型的动物以完全不同的方式进食。

    【讨论】:

      【解决方案5】:

      如果您要创建多个类都实现了这些功能,而实现方式只是略有不同,这将是一项艰巨的工作。

      在这种情况下,您可以轻松地在类层次结构中创建另一个层,该层实现了Animal,但它是所有以某种方式进食的动物的祖先类,例如

      class Herbivore implements Animal {
        public void eat(Object food) {
         ...
        }
      }
      
      class Cow extends Herbivore..
      class Horse extends Herbivore..
      

      您可以使用super.eat() 覆盖eat 并仅更改轻微的部分..

      您应该同时期待代码重用和组件封装。那么如果您的接口确实不能表征类本身,而只是它的一个组件,那么您可以按照 Carl Manaster 的建议进行组合。

      【讨论】:

        【解决方案6】:

        您应该将接口视为一种权威的行为声明,它首先与实现问题无关。

        如果您想避免代码重复,那么您可以将抽象基类与接口结合使用。然后,您可以在此处实现所有可能在所有接口实现类中重复的东西。

        HTH.
        托马斯

        【讨论】:

          【解决方案7】:

          使用接口更多的是让消费代码知道你对它的期望,而不是你需要关心消费代码的细节。

          例如,我们经常使用接口的一种方式是在业务层/数据访问层中。

          由于我们的业务层 (BL) 组件将直接与数据访问层 (DAL) 组件通信,因此 DAL 无法直接与 BL 通信。如果 DAL 想要使用对象而不是单个字段会发生什么?您必须定义自己的 DAL 对象,并使用您刚刚收到的输入对它们进行水合。基本上,更多的工作,更多的资源消耗,以及代表相同数据的多个对象,这让维护成为一场噩梦。

          但是,如果您在 DAL 中定义接口,您可以告诉 DAL 的使用者它期望什么。然后您可以在 BL 中实现这些接口并传递接口的实例而不是 BL 对象。

          接口都是关于抽象出非绝对必要的实现细节。

          [编辑] 如果您有很多执行类似操作的对象,那么结合使用接口和基类以及可覆盖/虚拟方法可能比仅使用接口更有用。

          【讨论】:

            【解决方案8】:

            还有旧线程,我知道。但我刚刚阅读了“接口是在 Java 中创建多重继承的唯一方法”。这是非常错误的,因为委托(或 Carl 所说的“组合”)是获得多重继承的唯一方法(请记住:“委托就是继承”,嗯,差不多)。

            您只需要接口告诉开发人员“嘿,别忘了委托这个或那个类”!仅需要接口作为正确委派(或通常:实现)的提醒,但它们不能继承任何代码。根本不需要多重继承接口。

            实际上,创建工作程序并不需要接口,它们只是没有任何功能或功能代码的助手。顺便说一句,Thomas 对抽象类的看法非常正确,这些比接口重要得多,因为您可以从中获得可重用的代码。

            通常,当我编写一个 java 应用程序时,我只在最后创建接口,作为未来程序员的助手。或者我根本不创建任何接口;D

            【讨论】:

            • 接口不是助手。它们不是提醒开发人员实现方法的合同。接口将被编码,以便您可以将特定实现与需要功能的地方解耦。
            【解决方案9】:

            一个主要原因是您可以使用接口引用创建对象,类似于抽象方法。当你这样做时,每个实现接口的对象都可以分配给它。例如,如果 Dog 和 Car 都实现了 Washable,那么你可以这样做:

            可洗 wD=new Dog();

            可洗 wC=new Car();

            如果 Washable 有公共抽象方法wash(),那么你可以这样做:

            wD.wash();

            wC.wash();

            以及它们各自的方法将被调用。这也意味着您可以接受接口作为方法的参数,这意味着您不必添加不必要的代码来处理实现某个接口的每个类。

            更详细的解释请看这里:http://www.artima.com/objectsandjava/webuscript/PolymorphismInterfaces1.html

            【讨论】:

            • 很好的解释
            【解决方案10】:

            泛化

            使用 JAVA 接口我们可以实现跨子类的泛化。泛化在这里意味着具有相同行为的子类以不同的方式实现。

            标准化

            接口允许为实现它的所有子类设置标准化。它指定子类必须具有的“什么”,但不强制要求它应该具有什么。

            100% 抽象

            接口体提供100%抽象,子类不会错过任何抽象方法的实现。如果我们使用抽象类,这是不可能的。

            去耦合(松散耦合)

            在开发应用程序时,与最终用户交互的代码可以通过使用接口松散耦合到服务器上运行的代码[B L C]。

            多重继承

            使用接口我们可以实现使用类无法实现的 MI。

            【讨论】:

              【解决方案11】:

              并且它没有这样的实现 那么任何使用你的界面的人都有 从头开始写..每次。

              接口的每个实现都可以不同。关键是您可以在不知道实现的情况下使用接口。考虑示例:

              public interface ILogger
              {
                  void WriteMessage(string message);
              }
              

              您的应用程序可以使用ILogger 接口来记录错误/调试信息等。但是记录器的实现方式并不重要——它可以是FileSystemLogger,或DatabaseLogger,或任何其他实现。因此,您将能够随时替换实现,而无需更改代码中提到日志记录的所有位置。

              【讨论】:

                【解决方案12】:

                您正在倒退。 不是首先考虑实现,而是首先考虑行为(如方法签名所述)。然后,您在基类中适当地实现行为,从而提供一个更加灵活、可扩展的系统。 您很快就否定了“按合同设计”,但它是关键的设计策略,也是 Web 服务、SOA 等的基础。

                【讨论】:

                  【解决方案13】:

                  这并不是一个真正的答案,而是一个我在考虑接口时发现有用的示例,但考虑一下需要方法的接口Comparable<T>

                  public int compareTo(T anotherObject)
                  

                  用户可以随心所欲地实现这一点。例如,如果是Person implements Comparable<Person>,则可以根据姓氏然后名字进行比较,忽略大小写。或者它可以基于年龄等。但是用户想要。实现这个接口非常有用,因为它允许用户使用像Collections.sort() 这样的东西,它要求要排序的元素需要具有可比性(否则如何进行比较?)

                  【讨论】:

                    猜你喜欢
                    • 2011-02-01
                    • 1970-01-01
                    • 2013-12-14
                    • 1970-01-01
                    • 2011-06-14
                    • 2014-08-21
                    • 2011-05-21
                    • 2011-09-20
                    • 1970-01-01
                    相关资源
                    最近更新 更多