除去Scala的糖衣(13) -- Default Parameter Value

来源:互联网 发布:宿迁宽带测速软件 编辑:程序博客网 时间:2024/04/28 02:11

欢迎关注我的新博客地址:http://cuipengfei.me/

 

好久没有写博客了,上一次更新竟然是一月份。

说工作忙都是借口,咋有空看美剧呢。

这半年荒废掉博客说到底就是懒,惯性的懒惰。写博客这事儿,一丢掉就很久捡不起来。

闲话到此为止,下面进入正题。

Default parameter value,默认参数值。 这个很容易理解,给参数一个默认值,如果调用者不显式指明参数值,则使用默认值。如果显式指明了,那就用显式指明的值。

举个例子:

1
def hello(name: String = "world") = println("hello " + name)

这个函数,如果我们不给它传参数,它就会打印hello world。就像这样:

1
hello()

如果给了参数:

1
hello("everybody")

则打印hello everybody。

这个语言特性都有哪些应用场景呢?

它经常用来避免过多的重载。一个很常见很典型的例子就是构造函数重载。

在Java中,为了让调用者能够比较容易的创建某个类的实例,我们通常会提供几个参数列表比较短的构造函数。而这些构造函数存在的唯一意义就是为了写死某几个参数值。而在Scala中,有了这个语言特性,我们就无需那么麻烦了。

那这个语言特性是如何实现的呢?实际上简单的一塌糊涂。

这样一段代码:

1234567
class Greeter {  def hello(name: String = "world") = println("hello " + name)}class AnotherClass {  new Greeter().hello()}

我们的Greeter类含有前面提到过的hello方法。在AnotherClass里调用了hello,并且没有显式指明参数值。

上面的Scala代码生成的bytecode反编译成Java是这样的:

1234567891011121314151617
public class Greeter {    public void hello(String name) {        Predef..MODULE$.println(new StringBuilder().append("hello ").append(name).toString());    }    public String hello$default$1() {        return "world";    }}public class AnotherClass {    public AnotherClass() {        Greeter qual$1 = new Greeter();        String x$1 = qual$1.hello$default$1();        qual$1.hello(x$1);    }}

可以看到,我们所定义的hello方法反编译出来看起来很普通,就是个接受一个参数的方法。

而在Greeter类中,编译器为我们加入了另一个方法hello$default$1,这个方法就是返回一个写死的字符串,其值为world。

在AnotherClass中调用hello时,写死的字符串被取到,然后传进了hello里。

这样,被调用者提供了参数的默认值,调用者在调用时取得该值,然后传入方法。

题外话

到这里我不禁联想起C#中的默认参数值的实现方式。

在C#中,默认参数的值会被编译成调用者的一个常量,而不是像Scala一样的由被调用者提供。

这样看起来貌似没啥区别,不就是写死的值换个地方吗?

其实不然,如果被调用者在A程序集内,调用者在B程序集内,那么A更新时,B就必须重新编译才能得到最新的默认值。也就是说,如果当前部署环境中同时存在A和B,而后我们拿一个新版的A来替换老的,这时B仍然在传递老的默认参数值给A。这样就会造成一些看似很诡异的行为偏差。

如果对C#的默认参数值的实现有兴趣,请看我很久很久之前写的博客

现在想来,C#这一语言特性的设计者为什么要把它设计成如此容易出错的样子呢?

思而不得其解。

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝宝六个月了便秘怎么办 宝宝拉水酸臭味怎么办 50天婴儿不拉屎怎么办 六个月宝宝吃米粉便秘怎么办 纯母乳喂养的宝宝便秘了怎么办 换奶粉拉绿色是怎么办 2个月宝宝发烧怎么办 小宝绿色稀大便怎么办 新生儿吃奶粉大便干燥怎么办 婴儿拉绿色奶瓣怎么办 宝宝吃奶粉大便干燥怎么办 婴儿吃奶粉不大便怎么办 孩子喝奶粉拉大便干怎么办 吃奶粉拉不出来怎么办 一岁半宝宝睡觉抱着睡放不下怎么办 3月大婴儿拉奶瓣怎么办 70多天宝宝便秘怎么办 宝宝喝奶粉上火便秘怎么办 a2奶粉吃了便秘怎么办 两个月宝宝两天没有大便怎么办 婴儿一直拉肚子吃药也不好怎么办 吃奶粉的婴儿便秘怎么办 一个多月小狗便便不成形怎么办 3个月宝宝不拉屎怎么办 好几天不拉大便怎么办 20个月宝宝大便干燥怎么办 两月宝宝三天没大便怎么办 六个月宝宝大便干燥怎么办 五个月宝宝拉肚子怎么办拉水样 2个月婴儿拉稀水怎么办 两个月的宝宝拉肚子怎么办 两天了不拉大便怎么办 25天的宝宝便秘怎么办 2个月宝宝便秘怎么办 猫拉绿色稀水怎么办 50天的宝宝便秘怎么办 人工喂养大便次数少怎么办 4个月宝宝肠炎怎么办? 三个月的宝宝拉肚子有奶瓣怎么办 吃米粉后不拉屎怎么办 宝宝拉绿色稀水怎么办