我的新博客地址:http://cuipengfei.me/blog/2013/12/23/desugar-scala-4/

Scala中有一个type关键字,用来给类型或者是操作起别名,用起来很是方便。

比如这样:

1
type People = List[Person]

这样就是给List[Person](方括号是Scala的类型参数的写法)声明了一个别名,叫做People。

接下来就可以这样使用它:

1
2
3
  def teenagers(people: People): People = {
people.filter(person => person.age < 20)
}

这个代码编译之后没有什么神奇的,仅仅是把所有出现People这个字眼的地方都用List of Person替代了。

1
2
3
4
5
6
7
  public List<Person> teenagers(List<Person> people)
{
return (List)people.filter(new AbstractFunction1() { public static final long serialVersionUID = 0L;
public final boolean apply(Person person) { return person.age() < 20; }
});
}

这种给类型一个别名的特性只是一个小糖豆,不太甜,真正有趣的是给一类操作命名(联想C#中定义delegate)。

比如这样:

1
type PersonPredicate = Person => Boolean

接受一个Person,返回一个Boolean,我们把这一类用来判断一个人是否符合某个条件的操作统称为PersonPredicate。

然后我们可以定义以下predicate:

1
val teenagerPred: PersonPredicate = person => person.age < 20

然后前面写过的teenagers方法就可以这样重新定义:

1
2
3
  def teenagers(people: People): People = {
people.filter(teenagerPred)
}

按照这个思路下去,我们就可以开始composite functions了。比如说,我们跟人收税,就可以这么做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  type Tax = Person => Double
val incomeTax: Tax = person => person.income * 5 / 100
val kejuanzaTax: Tax = person => person.income * 20 / 100
def giveMeYourMoney(p: Person) = {
calculateTax(p, List(incomeTax, kejuanzaTax))
}
def calculateTax(person: Person, taxes: List[Tax]): Double = {
taxes.foldLeft(0d) {
(acc, curTax) => acc + curTax(person)
}
}

从一个人那里拿到钱,这种操作,我们称之为Tax。然后定义个税和苛捐杂税,或者也可以有任意多的税种。

然后就可以把任意的几个税种放在一个List里面,和calculateTax去composite了。

当然,没有type这个关键字,我们也可以composite functions。只不过就得写成这样:

1
2
val teenagerPred: (Person) => Boolean = person => person.age < 20
def incomeTax: (Person) => Double = person => person.income * 5 / 100

看着稍微有点眼花。

这种用type关键字给一种操作命名的代码反编译之后是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  public Function1<Person, Object> teenagerPred()
{
return new AbstractFunction1() { public static final long serialVersionUID = 0L;
public final boolean apply(Person person) { return person.age() < 20; } } ;
}
public Function1<Person, Object> incomeTax()
{
return new AbstractFunction1() { public static final long serialVersionUID = 0L;
public final double apply(Person person) { return person.income() * 5 / 100; } } ;
}
public Function1<Person, Object> kejuanzaTax()
{
return new AbstractFunction1() { public static final long serialVersionUID = 0L;
public final double apply(Person person) { return person.income() * 20 / 100; } } ;
}

可以看到所有这种接受一个参数,返回一个值的操作都是Function1<Person, Object>。

推测一下,接受两个参数,返回一个值的是不是该叫做Function2呢?

1
2
3
type TwoToOne = (String, Int) => Double
def twoToOneImpl: TwoToOne = (str, i) => 1

反编译之后,果不其然:

1
2
3
4
public Function2<String, Object, Object> twoToOneImpl()
{
return new Hello..anonfun.twoToOneImpl.1(this);
}

那不接收参数,只有返回值的呢?

1
2
3
  type NoInJustOut = () => String
def noInJustOutImpl: NoInJustOut = () => "hello world"

反编译之后,其实是变成了Function0 of String:

1
2
3
4
  public Function0<String> noInJustOutImpl()
{
return new Hello..anonfun.noInJustOutImpl.1(this);
}

到这里,我们可以总结一下type alia这个糖衣:

一个类型的type alias,类似于这样的:type t = x。编译器将在所有使用到t的地方把t替换为x。

对于一种操作的type alias,编译器将会根据参数列表和返回值类型的不同将其替换为对应的Function0,Function1,Function2 …… 一直到Function22。

如果我们真的定义一个超过二十二个参数的操作会如何呢?

1
2
3
4
5
6
7
8
  type twentyThree = (
String, String, String, String,
String, String, String, String,
String, String, String, String,
String, String, String, String,
String, String, String, String,
String, String, String
) => String

Scala编译器会直接告诉我们: type Function23 is not a member of package scala

去掉Scala的糖衣(4) -- Type Aliase的更多相关文章

  1. 测试驱动 ASP.NET MVC Type Aliase

    Type Aliase 去掉Scala的糖衣(4) -- Type Aliase 我的新博客地址:http://cuipengfei.me/blog/2013/12/23/desugar-scala- ...

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

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

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

    欢迎关注我的新博客地址:http://cuipengfei.me/ 好久没有写博客了,上一次更新竟然是一月份. 说工作忙都是借口,咋有空看美剧呢. 这半年荒废掉博客说到底就是懒,惯性的懒惰.写博客这事 ...

  4. scala中的self type

    scala目前的书籍有两<快学scala>和<scala编程>.资料确实不多,对这个语法使用只能结合使用进行理解. 先看源码: private[spark] trait Act ...

  5. Beginning Scala study note(8) Scala Type System

    1. Unified Type System Scala has a unified type system, enclosed by the type Any at the top of the h ...

  6. [翻译]The Neophyte's Guide to Scala Part 12: Type Classes

    The Neophyte's Guide to Scala Part 12: Type Classes 过去的两周我们讨论了一些使我们保持DRY和灵活性的函数式编程技术,特别是函数组合,partial ...

  7. scala学习笔记(四)样本类与模式匹配

    访问修饰符 格式:private[x]或protected[x],x指某个所属包.类或单例对象,表示被修饰的类(或方法.单例对象),在X域中公开,在x域范围内都可以访问: private[包名]:在该 ...

  8. Spark基础-scala学习(一、入门)

    Scala解析器的使用 REPL:Read(取值)-> Evaluation(求值)-> Print(打印)->Loop(循环).scala解析器也被称为REPL,会快速编译scal ...

  9. Scala详解

    1       快速入门... 4 1.1             分号... 4 1.2             常变量声明... 4 1.2.1         val常量... 4 1.2.2  ...

随机推荐

  1. JavaScript中isPrototypeOf函数

    转自:http://www.ijavascript.cn/shouce/javascript-isprototypeof-247.html JavaScript中 isPrototypeOf 函数方法 ...

  2. Cocos2d-x源代码解析(1)——地图模块(1)

    cocos通过加载tiled 生成的tmx文件来生成游戏地图.本文主要分析cocos加载地图模块的源代码.   如图所看到的,地图加载模块由以上几个类组成. 对外的入口是类CCTMXTiledMap, ...

  3. 定义查询构建器IFeatureLayerDefinition

    在宗地出图,需要实现,只显示某一户人的地块.在ArcMap里,有个定义查询,可只显示过滤后的要素. 在代码中,也比较好实现,使用IFeatureLayerDefinition接口即可. IFeatur ...

  4. T-SQL 之 公用表表达式(CTE)

    在编写T-SQL代码时,往往需要临时存储某些结果集.在CTE之前常用的两种临时存储结果集为:临时表和表变量.除此之外,还可以使用公用表表达式的方法. 公用表表达式(Common Table Expre ...

  5. Mysql创建、删除用户、查询所有用户等教程,提升您的MYSQL安全度!

    建议您不要使用mysql的root账号来为您的web页面连接数据库,这可能会导致用户通过网页获取到您的数据库账号密码,存在严重的安全隐患. 建议新建一账号,权限设置基本够用,然后使用那新建的账号来连接 ...

  6. ajax local.href不跳转的原因之一

    ajax local.href不跳转的原因之一 打开F12发现一直报 next.html is not a function…… 后来发现next少了(),看得我尴尬症都犯了

  7. 【BIRT】交叉报表中出现空值设置为默认值

    在使用BIRT做交叉报表的时候,往往会出现有些维度下的值是空值,例如如下报表: 那么我们可以为这些空值给出默认值,例如"-" 具体操作如下: 点击上图的[Cross Tab]后选中 ...

  8. windows+Linux【Composer安装指定版本laravel】

    在windows下安装的方法:(php.ini中openssl.dll扩展必须打开,且版本>=5.4) 方法一:使用安装程序 这是将 Composer 安装在你机器上的最简单的方法. 下载并且运 ...

  9. cxf利用接口规范写法发布webservice

    package cn.itcast.cxf; import javax.jws.WebService; @WebService public interface IHelloService { pub ...

  10. EL和自定义函数库

    问题:在数据显示的时候经常需要调用一些方法对需要显示的数据进行基本的处理,如: 数据过滤.求子串等操作.那么就需要使用EL表达式进行快速的函数调用. 引入HTMLFilter.java类 描述为函数 ...