大多数面向对象语言的接口名称都以大写的I开头,为什么Java不这样做呢?不遵循这一惯例的理由是什么?

为了证明我的意思,如果我想有一个用户界面和一个用户实现,我在Java中有两个选择:

类=用户,接口= UserInterface 类= UserImpl,接口=用户

在大多数语言中:

类=用户,接口= IUser

现在,您可能会争辩说,您总是可以为用户实现选择一个最具描述性的名称,这样问题就解决了,但Java正在推动POJO方法,大多数IOC容器广泛使用dynamicproxy。这两件事加在一起意味着您将使用单个POJO实现拥有许多接口。

所以,我想我的问题可以归结为:“是否值得遵循更广泛的接口命名约定,尤其是考虑到Java框架的发展方向?”


当前回答

这两者真的有区别吗:

class User implements IUser

and

class UserImpl implements User

如果我们讨论的是命名惯例?

就我个人而言,我不喜欢在接口之前使用I,因为我想对接口进行编码,我认为这在命名约定方面更重要。如果调用接口IUser,那么该类的每个消费者都需要知道它是IUser。如果调用类UserImpl,那么只有类和DI容器知道Impl部分,而使用者只知道他们正在使用User。

然后,我被迫使用Impl的时候,因为一个更好的名字本身没有出现,因为实现是根据实现命名的,因为这是它的重要之处,例如。

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO

其他回答

Java通常不使用IUser约定可能有几个原因。

Part of the Object-Oriented approach is that you should not have to know whether the client is using an interface or an implementation class. So, even List is an interface and String is an actual class, a method might be passed both of them - it doesn't make sense to visually distinguish the interfaces. In general, we will actually prefer the use of interfaces in client code (prefer List to ArrayList, for instance). So it doesn't make sense to make the interfaces stand out as exceptions. The Java naming convention prefers longer names with actual meanings to Hungarian-style prefixes. So that code will be as readable as possible: a List represents a list, and a User represents a user - not an IUser.

这两者真的有区别吗:

class User implements IUser

and

class UserImpl implements User

如果我们讨论的是命名惯例?

就我个人而言,我不喜欢在接口之前使用I,因为我想对接口进行编码,我认为这在命名约定方面更重要。如果调用接口IUser,那么该类的每个消费者都需要知道它是IUser。如果调用类UserImpl,那么只有类和DI容器知道Impl部分,而使用者只知道他们正在使用User。

然后,我被迫使用Impl的时候,因为一个更好的名字本身没有出现,因为实现是根据实现命名的,因为这是它的重要之处,例如。

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO

这是真正意义上更广泛的命名惯例吗?我更倾向于c++,而不是Java及其后代。有多少语言社区使用I约定?

如果这里有独立于语言的商店标准命名约定,请使用它。如果不是,请遵循语言命名约定。

在Wicket框架中也使用了“I”前缀,我很快就习惯了它。一般来说,我欢迎任何缩短笨重Java类名的约定。但是,在目录和Javadoc中,所有东西都按字母顺序排列在“I”下面,这很麻烦。

Wicket的编码实践类似于Swing,因为许多控件/小部件实例被构造为带有内联方法声明的匿名内部类。令人恼火的是,它与Swing有180度的不同,Swing为实现类使用前缀(“J”)。

“Impl”后缀是一个蹩脚的缩写,不能很好地国际化。如果我们至少用“小恶魔”的话,它会更可爱(也更短)。“Impl”用于IOC,特别是Spring,所以我们现在有点被它困住了。不过,在一个代码库的三个不同部分遵循三种不同的约定有点分裂。

正如另一位发帖者所说,通常更可取的做法是让接口定义功能,而不是类型。我倾向于不“实现”像“User”这样的东西,这就是为什么在这里描述的方式中“IUser”通常不是真正必要的。我经常把类看作名词,把接口看作形容词:

class Number implements Comparable{...}  
class MyThread implements Runnable{...}
class SessionData implements Serializable{....}

有时形容词没有意义,但我仍然通常使用接口来建模行为、动作、功能、属性等等……没有类型。

另外,如果你只创建一个User,并将其命名为User,那么还有IUser接口的意义何在?如果您将有几个不同类型的用户需要实现一个公共接口,那么在选择实现名称时,在接口上附加一个“I”会为您节省什么呢?

我认为一个更现实的例子是,某些类型的用户需要能够登录到特定的API。我们可以定义一个Login接口,然后有一个带有SuperUser、DefaultUser、AdminUser、AdministrativeContact等子类的“User”父类,其中一些会或不会在必要时实现Login(可登录的?)接口。