欢迎关注我的新博客地址: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中,有了这个语言特性,我们就无需那么麻烦了。

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

这样一段代码:

1
2
3
4
5
6
7
class Greeter {
def hello(name: String = "world") = println("hello " + name)
} class AnotherClass {
new Greeter().hello()
}

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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#这一语言特性的设计者为什么要把它设计成如此容易出错的样子呢?

思而不得其解。

除去Scala的糖衣(13) -- Default Parameter Value的更多相关文章

  1. Default Parameter Values in Python

    Python’s handling of default parameter values is one of a few things that tends to trip up most new ...

  2. 《理解 ES6》阅读整理:函数(Functions)(一)Default Parameter Values

    对于任何语言来说,函数都是一个重要的组成部分.在ES6以前,从JavaScript被创建以来,函数一直没有大的改动,留下了一堆的问题和很微妙的行为,导致在JavaScript中使用函数时很容易出现错误 ...

  3. python's default parameter

    [python's default parameter] 对于值类型(int.double)的default函数参数,函数不会保存对默认类型的修改.对于mutable objectd类型的默认参数,会 ...

  4. JavaScript函数的默认参数(default parameter)

    JavaScript函数的默认参数(default parameter) js函数参数的默认值都是undefined, ES5里,不支持直接在形参里写默认值.所以,要设置默认值,就要检测参数是否为un ...

  5. 去掉Scala的糖衣(4) -- Type Aliase

    我的新博客地址:http://cuipengfei.me/blog/2013/12/23/desugar-scala-4/ Scala中有一个type关键字,用来给类型或者是操作起别名,用起来很是方便 ...

  6. [Python] Pitfalls: About Default Parameter Values in Functions

    Today an interesting bug (pitfall) is found when I was trying debug someone's code. There is a funct ...

  7. 抹掉Scala的糖衣(14) -- Update Method

    欢迎关注我的新博客地址:http://cuipengfei.me/ 在Scala中,名字叫做update的方法是有特殊作用的. 比如: 1 2 3 val scores = new scala.col ...

  8. scala学习手记13 - 类继承

    在scala里,类继承有两点限制: 重写方法需要使用override关键字: 只有主构造函数才能往父类构造函数中传参数. 在java1.5中引入了override注解,但不强制使用.不过在scala中 ...

  9. default parameter value for ‘color’ must be a compile-time constant

    定义了一个函数,函数有一个参数是Color类型的可选参数,想要设置其默认值为Color.Black http://stackoverflow.com/questions/2804395/c-sharp ...

随机推荐

  1. sed 命令编辑文本

    1.sed 概述 sed 是一个非交互式文本编辑器.它能够对文本文件和标准输入进行编辑,标准输入能够是来自键盘输入.文件重定向.字符串.变量.甚至来自于管道文本. 2.sed工作流程简述 sed在处理 ...

  2. T-SQL 之 存储过程

    当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可以提高存储过程的性能. 一.存储过程的概念 存储过程Procedure是一组为了完成特定功能的SQL语句集合,经 ...

  3. Unity Editor类常用方法

    http://www.cnblogs.com/zhaoqingqing/p/3944718.html 一些比较常用的Editor功能我在之前的博客中也有提到过所以就不详细写啦,今天参考了一下 麒麟子( ...

  4. Cg入门21:Fragment shader - 2D纹理採样

    体纹理:是啥? tex2D 曾经仅仅能在Fragment程序中纹理採样 UV坐标系:事实上点为左下角,范围为[0,1].U为x轴,V为y轴 watermark/2/text/aHR0cDovL2Jsb ...

  5. 基于JUnit3.8的一个简单的测试程序

    实现一个简单的计算 注:目标类和测试类要放在同一包下, JUnit单元测试基础要点 目标类:Calculator.java package com.junit3_8; public class Cal ...

  6. webpack 编译图片文件 file-loader

    1.安装插件 npm i file-loader --save-dev  npm i url-loader --save-dev  npm install image-webpack-loader - ...

  7. 我们为什么在移动端项目中选择jQuery而不是Zepto

    1.文件大小比较 首先从cnd上(http://www.bootcdn.cn/)下载jquery和zepto. jquery下载的是2.2.4版本压缩: zepto下载的是是1.20压缩版本: 二个文 ...

  8. honeyd蜜罐配置和web监听脚本

    Honeyd的安装和配置 Honeyd软件依赖于下面几个库及arpd工具: (1)Libevent:是一个非同步事件通知的函数库. 通过使用 libevent,开发者能够设定某些事件发生时所运行的函数 ...

  9. model中设置默认值时 ,使用 lambda 与否的差别以及datetime的默认值方法

    'date': '2013-01-01'  #固定值 'date': time.strftime('%Y-%m-%d')  #启动时候的值 'date': lambda *a: time.strfti ...

  10. 关于Javascript表单验证

    //验证字符串非空        var Validator = {    VerityLib: {         IsNotEmpty: function (input) {        if ...