我在Java中有一个基本问题,但这是OOP中的一个普遍问题。为什么接口允许设置字段?这不是一个接口应该做的事情吗?
我理解它的方式,界面是英语中的形容词。所以,如果我的类实现了Runnable和Serializable接口,我确保用户我的类将满足Runnable和Seriablizable的条件。但是,这意味着接口是“无状态的”,但允许它们在Java中有字段......
我错过了什么吗?
答案 0 :(得分:54)
界面中的所有字段都是public static final
,即它们是常量。
通常建议避免使用此类接口,但有时您可以找到没有方法的接口,并且仅用于包含常量值列表。
答案 1 :(得分:20)
首先, OOP范例与 OOP实现在Java 之间存在差异,因此相同的单词可能意味着有点不同。
在OOP中,范例界面是你可以用对象(或对象可以为你做什么)。任何对象都可以有多个接口,从而扮演不同的角色。例如,某人可以作为程序员工作并且能够创建程序,但同时他可能是丈夫和父亲,因此能够为他的家庭支付账单并照顾孩子。这里"程序员","丈夫"和父亲"是接口,而person是实现它们的对象。注意,接口并不意味着存在用于实现对象的任何特定功能(字段),只是该对象应该能够执行的操作。
Java或多或少遵循这个想法,但任何范例实现都有自己的特性。 Java允许描述方法,即实现对象应该能够执行的操作,而不是任何实现细节,因此,没有关于对象字段或私有方法。
但常量(public final static
字段)怎么样?它们是实现或接口的一部分。它可能都是。例如。界面"程序员"可以将常量WORK_HOURS
设置为" 8"。因此,Java允许您在接口中描述常量。
请注意,Java只能帮助您进行良好的OOP设计,但它并不强烈要求它。特别是,并非对象的所有公共方法都应该存在于接口中。例如,getter和setter方法通常是公共的,但实际上它们是部分的实现,而不是接口,因此不值得将它们引入接口。
(请注意,我在这里描述的大部分内容都与Java中的主流OOP有关,但也有其他类型的OOP,例如基于原型的OOP,特别是在JavaScript中实现)。
答案 2 :(得分:4)
如果该接口引用常量怎么办?在界面中声明它们不是很自然吗?
interface IdFinder {
Serializable UNSAVED = new Serializable() {};
/** @returns the given entity's persistent identity,
or {@link UNSAVED} if it hasn't been saved yet,
or null if o is a value object that hasn't a
persistent identity of its own.
*/
Serializable getId(Object o);
}
答案 3 :(得分:2)
是的,您可以在界面中使用常量字段,但是当您说“它似乎与界面应该做的相反”时,您是对的,因为这不是一个好习惯。为什么要让所有类实现具有相同常量的接口?你可以简单地将它们放在使用它们的类中,或者如果你真的需要以某种方式导出它们,请将它们放在一个单独的类中,如下所示:
public class Constants {
private Constants() { }
public static final int ZERO = 0;
public static final int SOME_COMPLEX_NUM = 2124132L;
...
}
如果需要表示一组具有某种含义的常量字段,您还有枚举。我没有看到任何“用例”,你实际上需要在接口中使用常量。但可能是错的:)