7.4 小结
本章我们学习了对名字的有效作用范围进行限制的重要性。现在(2013 年)大量采用的是静态作用域。
变量在任何一种语言中都存在,但不能想当然认为它在任何语言中都是一样的,或者它从一开始就是现在这样的。事实上,语言的不同会带来各种差异,即使现在大家还在不断地进行各种讨论以寻求更好的处理方式。本章介绍了 Ruby 1.9 和 Python 3.0 中对变量作变更的例子。
虽然现在很少会使用动态作用域,但这一概念并不是完全没有用处。与静态作用域中作用域是源代码级别上的一块完整独立的范围不同,在动态作用域中,作用域则是进入该作用域开始直至离开这一时间轴上的完整独立的范围。与此相同的特征也体现在其他好多地方。比如,在某处理进行期间,一时改变某变量的值随后将原值返回的代码编写方式就相当于创建了自己专属的动态作用域。又如,异常处理与动态作用域也很相似,函数抛出异常时的处理方式受到调用函数的 try/catch 语句的影响。
面向对象中像 private 声明这样的访问修饰符,在限制可访问范围的作用上和作用域是非常相似的。private 将可访问范围限制在类之内,而 protected 将此范围扩大到其继承类。这和函数调用处的变更会影响到调用里面的操作这一动态作用域表现是相似的,两者都具有这么一个缺点,这就是影响范围没有能限制在代码的某一个地方。
比如 Java 语言,它是静态作用域语言,它的类可以在源代码的任意处被访问。这意味着类是具有全局作用域的。但是类的名字具有层次并且只有导入后才能被使用 14,这避免了全局变量带来的无意的名字冲突。 但是不管是全局变量还是类的静态成员都可以在源代码的任意地方被变更。这提醒我们,在享受使用上的便利的同时,要谨防滥用导致的代码难以理解的情况发生 15。
14java.lang 这样的包里的类除外。
15对于习惯了 java 语言设计模式的人,这样说或许传达更清楚些:不要把单例模式(singleton pattern)作为全局变量的替代来使用。
作用域是编写易于理解的代码的有力工具,很多地方都应用了这一概念。
