此问题已在此处有答案:
Interface naming in Java [closed](11个回答)
7年前关闭。
如何命名您创建的不同类/接口?有时候我没有实现信息可以添加到实现名称中,比如接口FileHandler
和类SqlFileHandler
。
当这种情况发生时,我通常将接口命名为“正常”名称,如Truck
,并将实际的类命名为TruckClass
。
在这方面,你如何命名接口和类?
此问题已在此处有答案:
Interface naming in Java [closed](11个回答)
7年前关闭。
如何命名您创建的不同类/接口?有时候我没有实现信息可以添加到实现名称中,比如接口FileHandler
和类SqlFileHandler
。
当这种情况发生时,我通常将接口命名为“正常”名称,如Truck
,并将实际的类命名为TruckClass
。
在这方面,你如何命名接口和类?
9条答案
按热度按时间vybvopom1#
Interface
是什么不是ITruck
,因为它不是ITruck
,而是Truck
。Java中的
Interface
是Type。然后你有DumpTruck
,TransferTruck
,WreckerTruck
,CementTruck
等implements Truck
。当你使用
Interface
来代替一个子类时,你只需要将它转换为Truck
。如List<Truck>
。把I
放在前面只是Systems Hungarian style符号tautology,它只会增加更多的东西来输入代码。所有现代Java IDE的标记接口和实现等都没有这个愚蠢的符号。不要称之为
TruckClass
,它是tautology,就像IInterface
同义反复一样糟糕。如果它是一个实现,它就是一个类。这条规则的唯一真实的的例外,总是有例外,可能是像
AbstractTruck
这样的东西。因为只有子类会看到这个,你永远不应该转换到Abstract
类,它确实添加了一些信息,该类是抽象的,应该如何使用。您仍然可以想出一个比AbstractTruck
更好的名称,并使用BaseTruck
或DefaultTruck
,因为abstract
在定义中。但是由于Abstract
类不应该是任何面向公共接口的一部分,我相信这是一个可以接受的例外。创建构造函数protected
对于跨越这一鸿沟有很大帮助。后缀
Impl
也只是更多的噪音。更多的同义反复。任何不是接口的东西都是实现,即使是部分实现的抽象类。你打算把那个愚蠢的Impl
后缀放在每个Class的每个名字上吗?Interface
是一个关于公共方法和属性必须支持的契约,它也是Type信息。所有实现Truck
的东西都是Truck
的Type。查看Java标准库本身。你看到
IList
,ArrayListImpl
,LinkedListImpl
了吗?不,你看到的是List
和ArrayList
,还有LinkedList
。这里有一个很好的article关于这个确切的问题。任何这些愚蠢的前缀/后缀命名约定都违反了DRY原则。此外,如果你发现自己添加
DTO
,JDO
,BEAN
或其他愚蠢的重复后缀到对象,那么它们可能属于package而不是所有这些后缀。正确打包的名称空间是自文档化的,并减少了这些构思非常糟糕的专有命名方案中所有无用的冗余信息,大多数地方甚至在内部都没有以一致的方式遵守这些命名方案。如果您能想到的使
Class
名称唯一的方法是使用Impl
作为后缀,那么您需要重新考虑是否使用Interface
。因此,当您有一个Interface
和一个不是从Interface
唯一专用化的Implementation
时,在大多数情况下可能不需要Interface
。然而,一般来说,为了可维护性、可测试性和模拟,最好的做法是提供接口。参见this answer for more details。
另请参考Martin Fowler关于InterfaceImplementationPair主题的有趣文章
3bygqnnd2#
我在这里看到的答案表明,如果你只有一个实现,那么你就不需要接口。这与依赖注入/控制反转原则背道而驰(不要打电话给我们,我们会打电话给你!).
所以,是的,在某些情况下,你希望简化你的代码,并通过依赖注入的接口实现(这也可能是代理的-你的代码不知道!即使您只有两个实现-一个是用于测试的Mock,另一个是注入到实际生产代码中的-这也不会使接口变得多余。一个有良好文档记录的接口建立了一个契约,它也可以由一个严格的模拟实现来维护以进行测试。
事实上,您可以建立让模拟实现最严格接口约定的测试(为不应为null的参数抛出异常等)并捕获测试中的错误,在生产代码中使用更有效的实现(不检查不应该为null的参数是否为null,因为mock在测试中抛出了异常,并且您知道这些参数不是null,因为在这些测试之后修复了代码,例如)。
对于新手来说,依赖注入/IOC可能很难掌握,但是一旦你了解了它的潜力,你就会想在所有地方使用它,你会发现自己一直在制作接口--即使只有一个(实际生产)实现。
对于这个实现(您可以推断,并且您是正确的,我认为用于测试的mock应该称为Mock(InterfaceName)),我更喜欢名称Default(InterfaceName)。如果沿着更具体的实现,可以适当地命名。这也避免了我特别不喜欢的Impl后缀(如果它不是一个抽象类,当然它是一个“impl”!).
我也更喜欢“基地(InterfaceName)”而不是“Abstract(InterfaceName)”,因为在某些情况下,您希望基类以后成为可示例化的,但现在您被名称“Abstract”卡住了(InterfaceName)",这会迫使您重命名类,可能会引起一点小混乱-但如果它总是Base(InterfaceName),移除抽象修饰符不会改变类的性质。
5us2dqdw3#
接口的名称应该描述接口所代表的抽象概念。任何实现类都应该有某种特定的特征,可以用来给予它一个更具体的名字。
如果只有一个实现类,并且您想不出任何使其特定的东西(希望将其命名为
-Impl
),那么看起来根本没有理由拥有接口。uhry853o4#
我倾向于遵循Java Core/Sun建立的伪约定,例如。在集合类中:
List
-“概念”对象的接口ArrayList
-接口的具体实现LinkedList
-接口的具体实现AbstractList
-抽象的“部分”实现,以协助自定义实现我以前也做过同样的事情,在AWT事件/监听器/适配器范例之后对我的事件类进行建模。
eqoofvh95#
标准的C#约定(在Java中也很好用)是在所有接口前面加上
I
-因此您的文件处理程序接口将是IFileHandler
,卡车接口将是ITruck
。它是一致的,并且很容易区分接口和类。ie3xauqp6#
我喜欢用接口名来表示接口描述的合约,比如“Comparable”或“Serializable”。像“卡车”这样的名词并不能真正描述卡车的特性--卡车的能力是什么?
关于公约:我曾经参与过的项目中,每个界面都以“I”开头;虽然这与Java约定有些不同,但它使查找接口变得非常容易。除此之外,“Impl”后缀是一个合理的默认名称。
um6iljoc7#
有些人不喜欢这样,它更像是一个.NET约定而不是Java,但你可以用大写的I前缀命名你的接口,例如:
反对这种命名约定的人可能会争辩说,你不应该关心你在代码中是使用接口还是对象,但我发现它更容易阅读和理解。
我不会用“Class”后缀来命名实现类。这可能会导致混淆,因为您实际上可以使用“类”(即类型)对象,但在您的示例中,您不是在处理类对象,而是在处理一个普通的旧对象。
wa7juj8i8#
我使用这两种约定:
如果接口是一个众所周知的模式的特定示例(例如服务,DAO),那么它可能不需要“I”(例如UserService,AuditService,UserDao),所有没有“I”的工作都很好,因为后缀决定了 meta模式。
但是,如果你有一些一次性或一次性的东西(通常是一个回调模式),那么它有助于将它与一个类区分开来(例如。IAsynchCallbackHandler、IUpdateListener、IComputeDrone)。这些是为内部使用而设计的特殊用途接口,有时IInterface会引起注意,操作数实际上是一个接口,因此乍一看很清楚。
在其他情况下,您可以使用I来避免与其他常见的具体类(ICubber,IPrincipal vs Subject或Principal)发生冲突。
kx7yvsdv9#
TruckClass
听起来像是Truck
的一个类,我认为推荐的解决方案是添加Impl
后缀。在我看来,最好的解决方案是在实现名称中包含一些信息,在特定的实现中发生了什么(就像我们在List
接口和实现中所做的那样:ArrayList
或LinkedList
),但有时您只有一个实现,并且由于远程使用(例如)而必须具有接口,那么(如开头所述)Impl
就是解决方案。