Scala讲座:全局变量问题的解决
2015-04-20 13:17
239 查看
转载自:http://developer.51cto.com/art/200909/153286.htm
本文开始Scala讲座的第一部分内容,即用面向对象和函数式方法来解决全局变量问题,希望大家喜欢。文中有一个“引用的透明性”这个需要重点关照一下。
本文节选自最近在日本十分流行的Scala讲座系列的第七篇,由JavaEye的fineqtbull翻译。本系列的作者牛尾刚在日本写过不少有关Java和Ruby的书籍,相当受欢迎。fineqtbull由于时间关系先翻译了他认为最精彩的第七篇,这篇文章节选了第七篇中关于Scala全局变量的描述。
前言
这个连载也持续了不少的“刺激”内容了,这次为还没有习惯函数式编程的读者写一些东西。
这样写那好像我就是函数式编程的高手了,其实不是。到现在为止做的尽是Java的工作,从去年开始对于羽生田先生的Scala工作感兴趣之后投身于Scala语言以来,一直没有习惯函数式的思考方法,整天在这里面摸爬滚打。看了大量文章,写了大量代码之后终于觉得抓住了函数式编程的重点。
用面向对象和函数式方法来解决全局变量问题
关于需要函数式编程的动机,想从“全局变量问题”这个侧面来考虑一下。
“全局变量问题”是有关程序维护方面的问题(图1)。在编写多模块共享全局变量的时候,很难知道在何时哪个模块使用了该全局变量,程序也就比较容易出错了。而且,当准备删除全局变量时,由于不知道是否还有其他模块在使用它,所以最终把全局变量的定义留在那里不动了。类似情况大家都应该碰到过吧。
Scala讲座 图1:全局变量问题
解决“全局变量问题”有两个方法,一是收窄数据的有效范围;二是使变量被赋值一次后就不能更改。
面向对象的方式采取的是第一种方法。多模块共有的数据被封装在“对象”中,只有在“对象”内部才能够被使用(图 2)。
Scala讲座 图2:面向对象方式下解决全局变量问题的方法
函数式语言采用的是第二种方法,也就是一旦给变量赋值后该变量的值将不会改变(图3)。
Scala讲座 图3:函数式语言解决全局变量问题的方法
因此,下述的代码可以认为将数字“100”绑定在变量“price”上。感觉上就像变量“price”可以像数字“100”那样被使用。以前的连载也提到过,Scala中如果用val来定义变量的话,该变量将不能被重新赋值。为了正真的函数式编程就用val来定义变量吧。
scala> val price = 100
price: Int = 100
这样使变量的再赋值变得不可能之后,就能保证引用的透明性了。也就是说,使用同样的值作为参数来调用同一函数的情况下,任何时候取得的返回值都是一致的。
例如面向对象的情况下,由于对象实例含有内部状态,所以一旦内部状态改变后,即使使用相同的参数向同一个对象实例传递消息,取得的结果也有可能不同(图4)。如果是函数式编程的话就没有这种“副作用”了。
Scala讲座 图4:副作用概念图
本文开始Scala讲座的第一部分内容,即用面向对象和函数式方法来解决全局变量问题,希望大家喜欢。文中有一个“引用的透明性”这个需要重点关照一下。
本文节选自最近在日本十分流行的Scala讲座系列的第七篇,由JavaEye的fineqtbull翻译。本系列的作者牛尾刚在日本写过不少有关Java和Ruby的书籍,相当受欢迎。fineqtbull由于时间关系先翻译了他认为最精彩的第七篇,这篇文章节选了第七篇中关于Scala全局变量的描述。
前言
这个连载也持续了不少的“刺激”内容了,这次为还没有习惯函数式编程的读者写一些东西。
这样写那好像我就是函数式编程的高手了,其实不是。到现在为止做的尽是Java的工作,从去年开始对于羽生田先生的Scala工作感兴趣之后投身于Scala语言以来,一直没有习惯函数式的思考方法,整天在这里面摸爬滚打。看了大量文章,写了大量代码之后终于觉得抓住了函数式编程的重点。
用面向对象和函数式方法来解决全局变量问题
关于需要函数式编程的动机,想从“全局变量问题”这个侧面来考虑一下。
“全局变量问题”是有关程序维护方面的问题(图1)。在编写多模块共享全局变量的时候,很难知道在何时哪个模块使用了该全局变量,程序也就比较容易出错了。而且,当准备删除全局变量时,由于不知道是否还有其他模块在使用它,所以最终把全局变量的定义留在那里不动了。类似情况大家都应该碰到过吧。
Scala讲座 图1:全局变量问题
解决“全局变量问题”有两个方法,一是收窄数据的有效范围;二是使变量被赋值一次后就不能更改。
面向对象的方式采取的是第一种方法。多模块共有的数据被封装在“对象”中,只有在“对象”内部才能够被使用(图 2)。
Scala讲座 图2:面向对象方式下解决全局变量问题的方法
函数式语言采用的是第二种方法,也就是一旦给变量赋值后该变量的值将不会改变(图3)。
Scala讲座 图3:函数式语言解决全局变量问题的方法
因此,下述的代码可以认为将数字“100”绑定在变量“price”上。感觉上就像变量“price”可以像数字“100”那样被使用。以前的连载也提到过,Scala中如果用val来定义变量的话,该变量将不能被重新赋值。为了正真的函数式编程就用val来定义变量吧。
scala> val price = 100
price: Int = 100
这样使变量的再赋值变得不可能之后,就能保证引用的透明性了。也就是说,使用同样的值作为参数来调用同一函数的情况下,任何时候取得的返回值都是一致的。
例如面向对象的情况下,由于对象实例含有内部状态,所以一旦内部状态改变后,即使使用相同的参数向同一个对象实例传递消息,取得的结果也有可能不同(图4)。如果是函数式编程的话就没有这种“副作用”了。
Scala讲座 图4:副作用概念图
相关文章推荐
- c语言全局变量和局部变量问题及解决汇总
- QT 全局变量所遇见的问题,以及参考网上的解决方法,做个总结,提醒自己
- ajax给全局变量赋值问题解决示例
- c语言全局变量和局部变量问题及解决汇总
- 解决多次include后全局变量global失效的问题
- 【C#】类单例 可以解决全局变量的问题
- 解决spring boot集成jsp时EL表达式获取全局变量值为空的问题
- 解决Linux(Ubuntu)环境变量配置无效的问题:JDK,Hadoop,Spark,Scala等
- 问题解决笔记(全局变量,MFC关联变量)
- AJAX回调函数内部给全局变量赋值的问题与解决
- 解决C++全局变量只能初始化不能赋值的问题
- $.ajax()给全局变量赋值问题解决示例
- ajax给全局变量赋值问题解决示例
- Ajax修改全局变量问题解决方法(Zepto版)
- STM8全局变量溢出问题解决
- 解决spring中注入不能是全局变量的问题
- 网博士解决全局变量不开启问题
- C/C++语言中全局变量重复定义问题的解决方法
- 解决Ajax全局变量赋值的问题
- javascript中运用闭包和自执行函数解决大量的全局变量问题