接口的目的仍在继续
好的,我认为接口是一种强制对象实现一定function的方法,而不必使用inheritance。 有点像合同。 我半看到了他们的观点。
但是,如果您在界面中拥有的是:
public interface animal{ void eat(object food); }
并且没有这样的实现,那么每次使用你的界面的人都必须从头开始编写它。
如果你要创建一些所有实现这些function的类,并且实现只是略有不同,这将是一项艰苦的工作。
任何有助于理解这一点的人都表示赞赏,因为我知道这非常重要。
接口是在Java中创建多重inheritance的唯一方法。
假设你创建了一个Animal
类。 包括人类在内的所有动物都会扩展它。 并且这些动物中的每一种都inheritance了常见的方法,如吃,呼吸等。
但现在让我们说你有一个MathProblem
类。 并且您希望通过将问题传递给solve(MathProblem problem)
方法来使某些类可以解决该问题。 而且你知道Human
,也可能是Computer
可以解决数学问题。 所以他们都需要能够解决这个问题。 您可能可以让计算机扩展一些具有该方法的MathSolver
类,但Human已经扩展了Animal,并且无法扩展其他任何内容。 因此,更好的方法是使MathSolver成为一个接口,同时拥有Human
, Computer
和任何其他需要解决问题的类来实现它。
还要注意,人和Computer
可能以完全不同的方式解决问题,因为它们具有不同的对象。 这就是接口最适合的。 定义跨越多个inheritance层次结构的某些function,并且可以具有非常不同的实现,但是都可以传递给接受其中任何一个的方法。 想想Comparable
接口; 它不是特定类别的物体所具有的东西,所有类型的东西都可以进行比较,并且通常以非常不同的方式进行比较。 但是你总是可以在Comparable
对象List
上调用sort,因为你知道它们有一定的顺序,无论它们是Numbers
, Animals
, Computers
还是其他任何东西(只要它们实现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
- Spring – 将BindingResult添加到新创建的模型属性中
- 使用prepareRenderer方法将鼠标hover在JTable单元格上时显示图像
- setDefaultCloseOperation代替显示JFrame
- 使用https的async-http-client的CertificateException
- 调用Worklight Adapter并将列表视图中的JSON数据显示为字符串
- spring mvc one init binder适用于所有控制器
- 这是一个众所周知的设计模式吗? 它叫什么名字?
- 如何关闭全局对话框并在BlackBerry中显示另一个对话框?
- LibGDX:如何使平铺地图图块可点击?