我非常相信一致性,因此也就是惯例。
但是,我目前正在开发一个Java框架,其中这些约定(特别是get
/ set
前缀约定)似乎妨碍了可读性。例如,某些类将具有id
和name
属性,而使用o.getId()
代替o.id()
似乎完全没有意义,原因如下:
get
不传达其他语义,get
- 更少的命名架构。我从Java Collection
类(以及Java平台库中的其他类)获得了一些保证,这些类也违反了JavaBean约定(例如,他们使用size
而不是getSize
等。 )。
要解决这个问题:组件将从不用作JavaBean,因为它们无法以这种方式有意义地使用。
另一方面,我不是经验丰富的Java用户,我不知道其他Java开发人员对库的期望。我可以在这里遵循Java平台类的示例,还是被认为是糟糕的风格?在Java库类中违反get
/ set
约定是否被认为是一个错误的回顾?或者在不适用时忽略JavaBean约定是完全正常的吗?
(Sun code conventions for Java根本没有提到这一点。)
答案 0 :(得分:11)
如果您遵循相应的命名约定,那么第三方工具可以轻松地与您的库集成并使用您的库。他们会期待getX()
,isX()
等等,并尝试通过反思找到这些。
虽然你说这些目前不会作为JavaBeans公开,但我仍然会遵循这些惯例。谁知道你可能想要进一步做什么?或者在稍后阶段你可能想要提取这个对象的接口并创建一个可以通过其他工具访问的代理?
答案 1 :(得分:6)
我实际上讨厌这个惯例。如果它被一个提供访问器/修改器方法的真正的java工具所取代,那将会非常发生。
但我在所有代码中都遵循此约定。我们不单独编程,即使整个团队现在同意特殊约定,您也可以放心,未来的新人或将来维护您项目的团队将在开始时遇到困难......我认为获取/设置的不便并不像非标准的不便那样大。
我想提出另一个问题:java软件经常使用太多的访问器和修饰符(get / set)。我们应该更多地应用“告诉,不要问”的建议。例如,用“真实”方法替换B上的getter:
class A {
B b;
String c;
void a() {
String c = b.getC();
String d = b.getD();
// algorithm with b, c, d
}
}
通过
class A {
B b;
String c;
void a() {
b.a(c); // Class B has the algorithm.
}
}
这个重构获得了许多好的属性:
答案 2 :(得分:5)
违反Java库类中的get / set约定肯定是一个错误。我实际上建议你遵循约定,以避免知道为什么/何时不遵守约定的复杂性。
答案 3 :(得分:4)
Josh Bloch实际上在 Effective Java 中就此问题与你站在一起,在那里他主张get
- 更少的变体,用于不打算用作豆类的东西,为了便于阅读。当然,并不是每个人都同意Bloch,但它表明存在支持和反对倾销get
的情况。 (我认为它更容易阅读,所以如果YAGNI,放弃get
。)
关于集合框架中的size()
方法;当您查看具有Enum
和name()
的最新ordinal()
课程时,似乎不太可能只是一个“糟糕”的遗留名称。 (这可能是布洛赫是Enum
两个归属作者之一所解释的。☺)
答案 4 :(得分:2)
get-less架构在scala(和other languages)等语言中使用Uniform Access Principle:
Scala将字段和方法名称保存在同一名称空间中,这意味着如果方法名为count,我们就无法命名字段数。许多语言(如Java)没有此限制,因为它们将字段和方法名称保存在不同的名称空间中。
由于Java并不打算为“属性”提供UAP,因此最好使用get / set约定来引用这些属性。
UAP意味着:
Foo.bar
和Foo.bar()
相同,指的是阅读属性或属性的读取方法。Foo.bar = 5
和Foo.bar(5)
相同,指的是设置属性或属性的写入方法。在Java中,您无法实现UAP,因为Foo.bar
和Foo.bar()
位于两个不同的名称空间中。
这意味着要访问read方法,您必须调用Foo.bar()
,这与调用任何其他方法没有什么不同。
因此,这个get-set约定可以帮助区分该调用与其他调用(与属性无关),因为“模块提供的所有服务(此处只是读取/设置值,或计算它”)无法通过统一符号“。
它不是强制性的,而是一种从其他服务中识别与获取/设置或计算属性值相关的服务的方法。
如果UAP在Java中可用,则根本不需要该约定。
注意:size()
而不是getSize()
可能是为了Java而保留的遗留错误命名的咒语是'向后兼容:始终'。
答案 5 :(得分:0)
考虑这一点:可以告诉许多框架引用对象字段中的属性,例如“name”。在框架下,框架理解为首先将“name”转换为“setName”,从其单数参数中找出什么是返回类型,然后形成“getName”或“isName”。
如果您没有提供这种记录良好,明智的访问器/增变器机制,那么您的框架/库将无法与其他大多数库/框架一起使用。