我知道,对于C ++和Java来说,它是一个完善的命名约定,常量应该全部写成大写,下划线用于分隔单词。像这样(Java示例):
public final static Color BACKGROUND_COLOR = Color.WHITE;
public final static Color TEXT_COLOR = Color.BLACK;
这个命名约定很容易理解和遵循,但我问自己,为什么选择这个命名约定而不是变量的正常命名约定:
public final static Color backgroundColor = COLOR.WHITE;
public final static Color textColor = COLOR.BLACK;
Theres似乎不需要改变常量的外观。如果我们想为它们分配一个值,编译器将会阻止它。实际上它会产生问题,如果稍后将常量变为适当的变量(因为颜色可以配置为例如)。
那么将命名常量全部写成大写的最终原因是什么?历史原因?
答案 0 :(得分:28)
我认为这不是技术问题,而是心理问题。命名约定不是由编译器处理(计算机并不真正关注名称),而是为正在浏览代码的程序员提供尽可能多的信息,只需要尽可能少的工作。
使用不同的命名约定清楚地告诉读者,您正在阅读的内容是在编译时固定的内容,您无需通过代码来确定值的位置和方式。
答案 1 :(得分:16)
如果我知道某事是常数,我可以多次引用它并知道它不会改变。换句话说,我知道:
Color black = Colors.BLACK;
foo(black);
foo(black);
与:
相同foo(Colors.BLACK);
foo(Colors.BLACK);
有时候知道这很有用。我个人更喜欢.NET命名约定,即使用Pascal case来表示常量(和方法):
Foo(Colors.Black);
Foo(Colors.Black);
我不是一个狡猾的案例的忠实粉丝...但我确实认为常数显然是常数。
答案 2 :(得分:15)
我可以想象,最初,在C日,人们会使用预处理器象征性地实现“常量”:
typedef unsigned int Color;
#define BACKGROUND_COLOR 0xffffff
这样的“常数”只是美化文字,因此它们不像变量那样表现。例如,你不能接受这种“常数”的地址:
Color *p = &BACKGROUND_COLOR; // Breaks!
出于这个原因,让它们“脱颖而出”是有道理的,因为它们不仅仅是“你无法改变的变量”。
答案 3 :(得分:11)
我相信C ++这是一个从使用预处理器到#define常量值的过程。那时候,它是为了避免让预处理器在你的源代码中被践踏,因为C函数和变量名的通常约定会使它们混合大小写或小写。
从C ++的角度来看,我会说让你的常量全部大写是一个坏主意。由于这个原因,我不得不调试多个构建问题 - 请记住,C ++预处理器对命名空间和命名范围一无所知,并且很乐意替换它认为合适的内容,即使它是不合适的。
答案 4 :(得分:5)
在C(然后是C ++)中,使用预处理器#define
指令定义的符号全部用大写字母写成,向开发人员发出一个响亮的信号,即代码不像它看起来那样并且不被视为正常符号。常量最初并不存在于K& R C中(虽然const
稍后从C ++中恢复),因此开发人员使用#define
代替,因此使用了上限。
出于某种原因,这被扭曲成Java,因为“常数是上限”,因此当前被误导(IMO)惯例。
答案 5 :(得分:3)
我认为大写常量是来自C的不良遗产。背后的逻辑与使用下划线作为私有成员的前缀时相同。这是技术性的东西,已经由private
等Java关键字表示,或者在常量的情况下,static final
表示。
另请参阅:http://weblogs.java.net/blog/2006/09/28/case-against-uppercases
答案 6 :(得分:2)
使用大写常量长公式更容易阅读,您不必猜测哪个元素可以变化,哪个不可以。它当然只是一个惯例,但很有帮助。
答案 7 :(得分:2)
不要仅仅因为常量是宏而将ALL_CAPS用于常量。
来自C ++核心指南的quote总结了所有内容。
答案 8 :(得分:1)
可能你是对的。计算机和编译器(尤其是)并不像今天那么快。
乔尔·斯波尔斯基在one of his essays中提到他对新版Turbo Pascal的编译时间印象深刻。我记得编译不太大的程序(10-20KLOC)时在PC XT 10MHz的Turbo Pascal 5.0上覆盖大约需要20分钟......
我认为等待编译来检测错误是不可接受的。
这样的惯例有助于避免在编译中断时出现错误和浪费时间。
答案 9 :(得分:1)
这是一种解决方法,使您的开发工具无法以方便的方式识别标识符的属性。
与匈牙利符号非常相似。
当您的IDE变得更好时,您将不需要任何命名约定,但是该命令约定要求名称是关于标识符含义的全面信息。
即使这可能会发展:为什么不创建一个编程系统,你只需创建标识符,并添加属性,如“简要描述”,“类型”,...当工具到达时,可以方便地执行此操作,我在。“Intentional Programming”是一个提示。
答案 10 :(得分:1)
基本上,当人们爱上C,C ++& Java是新的还是尚未创建的,人们使用预处理器常量名称的全部大写,以表明它们实际上不是变量。
#define INT_CONST 4
#define STRING_CONST "Yello."
#define FLOAT_CONST 3.6122448
考虑到这是在C中定义一个真常量的唯一真正方法(如果你知道如何,它仍然可以改变const
变量),像这样的预处理器常量只被视为常量,因此all-caps名称的含义从预处理器常量转换为简单的常量。然后将其延伸到后来的语言中,成为标准的“consts = capitals”练习。
其他语言有自己喜欢的风格,但是(例如,C#和.NET更喜欢PascalCase),所以通常最好使用首选样式(如果有的话)。
答案 11 :(得分:0)
编程时,创建人类可以理解的代码非常重要。拥有命名约定有助于实现此目的。在查看未编写的代码时,这是最好的,并且使代码更易于维护,因为它很容易区分常量和变量。
答案 12 :(得分:0)
实际上,大多数C ++命名指南(包括ISO,Boost,Sutter& Stroustrup和Google)强烈反对使用全部大写字母命名常量。这是因为宏也使用全部大写,并且它们可能在头文件中遍布,可能会产生奇怪的行为。无论如何,人们仍然使用全部大写字母,因为他们从旧的C / K& R或旧遗留代码中学习。但是,在Modern C ++新代码中,除了宏之外,你应该避免使用全部大写。
我的宠物理论为什么所有大写字母都存在,就是在非常旧的机器上,使用数字键盘直接在机器代码中输入代码。当汇编语言到达现场时,它只使用全部大写,因为那时的键盘没有标准化,而且有些键盘受到限制,例如,使用相同的数字键盘输入功能手机中的字母。然后,它被转移到许多早期语言,如BASIC,这些都是一切。当实际的终端变得可用并且键盘开始变得标准化时,人们开始使用混合的情况而没有保留,所有的大写字母都被保留用于与函数和变量相比常见的常见事件。
大多数C ++指南现在都同意使用" k"作为常量的前缀,后跟带有下划线或CamelCase的名称。我个人更喜欢kCameCase,因为它很容易区分用under_scores命名的变量。
const float kFixedRadius = 3.141;
答案 13 :(得分:0)
这纯粹是为了帮助程序员一目了然地了解他或她正在看什么。有助于知道正在使用常量以使值不会改变不管你怎么称它。
关于编译器方面的事情并非如此。命名约定纯粹是惯例,而不是真正的技术限制。
答案 14 :(得分:-1)
编码转换是为了提高可读性。你不必使用字母。例如,Java允许使用$符号。
public final static Color $$ = COLOR.WHITE;
public final static Color $_ = COLOR.BLACK;
您也可以为变量编号,但这并不意味着它是一个好主意。 ;)
答案 15 :(得分:-3)
这绝对是Java中的技术问题。考虑:
import static com.test.constants.white;
public class Foo {
void bar(){
//String white = "black";
String whatAmI = white;
}
}
取消注释上一行之前和之后“whatAmI”的值是多少?
如果常量名称与局部变量名称具有相同的约定,则会导致REAL代码问题。常量应始终具有UPPERCASE约定以避免这种情况。