Type Aliase

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

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

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

比如这样:

  1. 1
  1. type People = List[Person]

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

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

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

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

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

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

比如这样:

  1. 1
  1. type PersonPredicate = Person => Boolean

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

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

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

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

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

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

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

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

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

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

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

看着稍微有点眼花。

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

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

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

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

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

反编译之后,果不其然:

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

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

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

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

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

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

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

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

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

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

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

【测试驱动 ASP.NET MVC】

http://msdn.microsoft.com/zh-cn/magazine/jj190803.aspx

【构建可测试 ASP.NET MVC 应用程序】

http://msdn.microsoft.com/zh-cn/magazine/dd942838.aspx

Pragmatic.Test.Drive.ASP.NET.MVC.Jun.2010

http://vdisk.weibo.com/s/DOlfks4ooGf 【图片可以点击】 

这本很薄的小书,今年读了至少4边,汤姆大叔翻译的js也看了几遍,受益匪浅

现在已经完成了60%的代码重构,因为垃圾站很简单,

虽然现在还没有深入到复杂模块和高难度模块单元测试,但普通的单元测试已经解决了我很多问题了

1 拖沓,以前写一个模块用老长时间,都是周末或平时有空写写,有时候记不起来几个月前定的需求,就一直放着,等想起来在写

现在先写完单元测试代码,明确的具体的规则,和目标,每次写之前先运行一次单元测试看哪里还没写,拖沓的毛病得到治疗。

个人感觉对创业团队更为重要:1防止拖沓 2防止赶工期出垃圾工程

2长函数,以前也不是有意写长函数,只不过写着写着写着就边长了,我也没办法,

现在写的时候先要想,我要怎么测试这个东西,复杂的东西不会测,写简单点,好测试

3成就感,,,,每次看着X号变绿色,心情都好了

测试驱动 ASP.NET MVC Type Aliase的更多相关文章

  1. 测试驱动 ASP.NET MVC 和构建可测试 ASP.NET MVC 应用程序

    [测试驱动 ASP.NET MVC] http://t.cn/8kdi4Wl [构建可测试 ASP.NET MVC 应用程序]http://t.cn/8kdi4Wj

  2. (转)ASP.NET MVC 第五个预览版和表单提交场景

    转自:http://ourlife.blog.51cto.com/708821/296171 上个星期四,ASP.NET MVC开发团队发布了ASP.NET MVC框架的“第五个预览版”.你可以在这里 ...

  3. ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库

    前段时间在园子里看到了小蝶惊鸿 发布的有关绿色版的Linux.NET——“Jws.Mono”.由于我对.Net程序跑在Linux上非常感兴趣,自己也看了一些有关mono的资料,但是一直没有时间抽出时间 ...

  4. 使用IdleTest进行TDD单元测试驱动开发演练(3) 之 ASP.NET MVC

    一.[前言] (1)本文将用到IOC框架Unity,可参照<Unity V3 初步使用 —— 为我的.NET项目从简单三层架构转到IOC做准备>(2)本文的解决方案是基于前述<使用I ...

  5. 视频教程--ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库

    说好的给园子里的朋友们录制与<ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库> 这篇博客相对应的视频,由于一个月一来没有时 ...

  6. ASP.NET MVC another entity of the same type already has the same primary key value

    ASP.NET MVC项目 Repository层中,Update.Delete总是失败 another entity of the same type already has the same pr ...

  7. 3.4 自动测试初步《精通ASP.NET MVC 5》

    概述 ASP.NET MVC 框架已被设计成易于建立自动测试,并易于采用诸如测试驱动开发(TDD)等的开发方法学.ASP.NET MVC 为自动化测试提供了一个理想平台. 从广义上讲,当今的 Web ...

  8. asp.net mvc项目使用spring.net发布到IIS后,在访问提示错误 Could not load type from string value 'DALMsSql.DBSessionFactory,DALMsSql'.

    asp.net mvc项目使用spring.net发布到IIS后,在访问提示错误 Could not load type from string value 'DALMsSql.DBSessionFa ...

  9. Cordova+Asp.net Mvc+GIS跨平台移动应用开发实战1-系统初步搭建(附演示,apk,全部源码)

    1.前言 身处在移动互联网的今天,移动应用开发炙手可热,身为程序猿的我们怎么能错过开发一款我们自己的APP.本人算是一个基于.net的GIS开发入门者(马上就大四啦), 暑假在学校参加GIS比赛有大把 ...

随机推荐

  1. SQL Server 2008杀数据库连接

    杀数据库连接: DECLARE @temp NVARCHAR(20) DECLARE myCurse CURSOR FOR SELECT spid FROM sys.sysprocesses WHER ...

  2. 使用pfile 启动oracle 实例时,启动失败---db_recovery_file_dest參数值在os上不存在。

    [oracle@vm22 ~]$ export ORACLE_SID=orcl [oracle@vm22 ~]$ sqlplus / as sysdba SQL*Plus: Release 10.2. ...

  3. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(7)-DBSession的封装

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(7)-DBSession的封装 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    ...

  4. .pb.h:9:42: fatal error: google/protobuf/stubs/common.h: No such file or directory

    看看这个你应该知道,找不到头文件,它可用于g++ 的-I 参数: -I/usr/local/lib/protobuf/include如需订购g++在/usr/local/lib/protobuf 以上 ...

  5. BZOJ 1004 HNOI2008 Cards Burnside引理

    标题效果:特定n张卡m换人,编号寻求等价类 数据保证这m换人加上置换群置换后本身构成 BZOJ坑爹0.0 条件不那么重要出来尼玛怎么做 Burnside引理--昨晚为了做这题硬啃了一晚上白书0.0 都 ...

  6. javascript权威指南(1)

    javascript常用知识点: http://www.cnblogs.com/pingfan1990/p/4309223.html Function.prototype.bind()Function ...

  7. ios结构体httpPost头结构

    ios结构体httpPost头结构 by 吴雪莹 NSString* urlStr = @"; NSURL* url = [NSURL URLWithString:urlStr]; NSMu ...

  8. WebBrowser!

    原文:WebBrowser! 我现在先放一些基础的文章在这里,以后再放别的上来官方范例连接http://www.microsoft.com/china/msdn/library/langtool/vc ...

  9. 多种语言socket编程集锦—win32

    原文 http://www.blogjava.net/huyi2006/articles/263831.html 借此地方整理以下socket编程的多种语言的实现,socket可以跨平台的通信,因此多 ...

  10. C程序中引用自定义的C函数模块

    原文:C程序中引用自定义的C函数模块 我们知道,刚开始接触C语言编程,一般都是在一个.c或者.cpp(以下只说.c)的文件中编写代码,其中一定会有一个入口函数, 也就是main()函数,你可以将程序代 ...