接口的目的仍在继续

好的,我认为接口是一种强制对象实现一定function的方法,而不必使用inheritance。 有点像合同。 我半看到了他们的观点。

但是,如果您在界面中拥有的是:

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

并且没有这样的实现,那么每次使用你的界面的人都必须从头开始编写它。

如果你要创建一些所有实现这些function的类,并且实现只是略有不同,这将是一项艰苦的工作。

任何有助于理解这一点的人都表示赞赏,因为我知道这非常重要。

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

假设你创建了一个Animal类。 包括人类在内的所有动物都会扩展它。 并且这些动物中的每一种都inheritance了常见的方法,如吃,呼吸等。

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

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

首选组合而不是inheritance。 这样,你就可以在一个类中实现(比如说)eat(),这个类作为数据成员被合并到你的所有动物中。 写一次,重用它,但是不能将一种function明确地绑定到另一种。

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

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

您应该将接口视为权威的行为声明 ,这与实现问题无关。

如果要避免代码重复,则将抽象基类与接口结合使用。 然后,您可以实现在所有接口实现类中可能重复的所有内容。

HTH。
托马斯

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

例如,如果你有一堆动物的Zoo对象(新的Tiger(),Lion(),Bear()),那么你的动物园可以为某个集合中的每个Animal a做一个a.eat(),它会起作用。 动物园并不关心有三种不同类型的动物以完全不同的方式进食。

如果你要创建一些所有实现这些function的类,并且实现只是略有不同,这将是一项艰苦的工作。

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

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

并且你可以通过使用super.eat()并仅更改轻微部分来覆盖eat

您应该同时期待代码重用和组件封装。然后,如果您的界面确实没有表征类本身,而只是它的一个组件,您可以按照Carl Manaster的建议进行组合。

使用接口更多的是为消费代码提供一种了解您对它的期望的方式,而不是需要关注消费代码的细节。

例如,我们在业务层/数据访问层中使用接口的方法之一。

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

但是,如果您在DAL中定义接口,则可以告知消费者DAL的期望。 然后,您可以在BL中实现这些接口,并传递接口的实例而不是BL对象。

接口都是关于抽象出实施细节,而这些细节并非绝对必要。

[编辑]如果你有很多做类似事情的对象,那么接口和带有可覆盖/虚方法的基类的组合可能比仅仅一个接口更有用。

老线程,我知道。 但我只读“接口是在Java中创建多重inheritance的唯一方法”。 这是非常错误的,因为委托(或像Carl所说的“compositon”)是获得多重inheritance的唯一方法(记住:“委托是inheritance”,好吧,差不多)。

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

实际上,你并不需要创建工作程序的接口,它们只是没有任何function或function代码的助手。 Btw Thomas对抽象类非常正确,它们比接口更重要,因为那是你可以从中获取可重用代码的地方。

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

概括

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

标准化

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

100%抽象

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

去耦(松耦合)

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

多重inheritance

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

并且没有这样的实现,那么使用你的界面的人必须从头开始写它…每次。

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

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

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

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

这不是一个真正的答案,而是在我考虑接口时我觉得有用的一个例子,但是考虑一下需要该方法的接口Comparable

 public int compareTo(T anotherObject) 

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

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

可水洗wD =新狗();

可水洗wC =新车();

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

wD.wash();

wC.wash();

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

有关更详细的说明,请参见此处: http : //www.artima.com/objectsandjava/webuscript/PolymorphismInterfaces1.html