我维护的库使用各种语义含义的字符串。例如,一个字符串是发票代码,另一个字符串是报价代码。根据这些类型,有这些语义类型和查找方法的讲解员。为了区分这些值的语义,我开始创建CharSequence
的实现,称为InvoiceCode
、QuotationCode
等。
我用Boost.Units作为灵感。在C++中使用物理方程时,绝对没有办法绕过它。使用普通double
将很快导致未知单位。我担心在我的图书馆中随处使用String
时也会发生同样的情况。
现在我的大学抱怨说,在调用我的图书馆之前从String
转换为语义类型太麻烦了,而在想要处理结果时又回到String
。
在我看来,我的大学应该在他们的代码中使用适当的类型。
所以最后的问题归结为:使用语义类型而不是String
Java 中的推荐和/或常见做法吗?
C++有两个关键功能,可以更轻松地使用用户定义的语义类型 - 转换运算符和运算符重载。Java没有两者中的任何一个,这使得你对语义类型的推动成为一场艰苦的战斗。
使用CharSequence
接口使库的用户在从库中获取数据时更容易避免转换为字符串。但是,传递所有这些InvoiceCode
和QuotationCode
对象需要调用方执行更多工作。
如果用户总是这样做
source.yourMethod(new QuotationCode(theirObject.quotationCodeString))
那么你是对的,他们应该用QuotationCode quotationCode
替换对象中的String quotationCodeString
,并获得它们的易用性。
另一方面,如果他们经常这样做
source.yourMethod(new QuotationCode("xyz-code"))
那么最好为众所周知的报价代码定义一个来源,让你的用户来写这个:
source.yourMethod(QuotationCode.XyzCode)
其中XyzCode
是一个众所周知的报价代码,您的用户将其硬编码为String
。
没有自己的域类型。
由于这类数据通常存储在数据库中,并且实际上最好在数据库中处理,因此自己的域值类最终可能会产生反作用。声明性业务规则,例如在XML
或某些DSL中也受到阻碍。
这取决于这些数据存储库的使用情况:像jOOQL这样的DSL,或者speedment或JPA。后者执行对象/关系映射,ID域通常由java类替换。
对于用户定义的代码,实际上不需要 java 类型:您不希望逐个处理硬编码值。这些应该以声明方式进行。例如,基于发票类别和合同的报告选择不应由嵌套的 ifs/switch 完成。
对于你所描述的,自然的"语义类型"是一个枚举。枚举类型 T 应该覆盖 'T toString((' 并实现 'static T fromString(String('(或者只使用 'valueOf(('(,这使得你的同事很容易使用,因为该类型会执行自己的转换。
您不需要运算符重载,这带来的问题多于解决的问题。您有转换方法,完全消除了对转换运算符的需求,因此与C++的比较是似是而非的。