在 Scala 2.10.0 之前类型的隐式转换必须通过隐式方法来完成,现在的 Scala 可以用 implicit class 来声明类, 并且它的主构造器 (Primary Constructor) 只有一个参数时,就可以用来把参数隐式转换成该类型。
能理解上面什么意思,知道怎么用隐式类吗? 就上面那句话,我自己都不知道在说什么。
首先要知道 Scala 先前是怎么依据隐式方法进行类型的隐式转换,其次又何谓主构造器呢? 关于 Scala 2.10.0 的 implicit class, 官方的解释在这里 http://docs.scala-lang.org/sips/pending/implicit-classes.html 再多说只能让大家更摸不到头,实例演示是王道:
- Windows 命令行 cmd 窗口系统默认的大小(80*40)对于现在的屏幕配置已经跟不上时代了,我们总是要把它改大些,而且缓冲区大小也想改得大大的。单纯的为当前的 Windows 命令行窗口修改显示大小和缓冲区大小就简单了,右键命令行窗口标题,属性里改屏幕缓冲区和窗口大小就是,系统会为与当前标题相同的命令行窗口记住你的设置,比如 C:\Windows\system32\cmd.exe。但是经常你又会打开不同标题的命令行窗口,如 Tomat,这时候它又是默认的 80*40 的窗口大小,又得改,再碰不同标题又要改。
于是能否直接修改系统默认的 cmd 窗口和它的缓冲区大小呢,以后碰到新的标题就参考于它。行的,方法是改注册表。
先来看下你可以在命令行下直接指定命令行窗口的大小了,进到命令行执行 mode,可以看到关于控制台的信息如下:
Status for device CON:
----------------------
Lines: 2000
Columns: 120 Read More
Java 的方法不支持多返回值,或者我们想达到返回多个值的效果时,不得不借用数组、列表或对象等来容纳多个值返回给调用者。这样使用起来不怎么优美,特别是为返回多个值而创造一个类成本有点高,如果 Java 也存在像 C# 那样的匿名类倒好。C# 如何使用匿名类返回多个值可参看本文后面的例子。
把 Scala 当作是一种脚本语言,它的灵活性就应该与 Perl 或 Ruby 看齐。Scala 的方法也可以有多个返回值,它实现些种行为,可借助于元组和列表类型,虽然你也可以发掘更多的实现方式,但到目前为止,我还是觉得用元组和列表最简单。
下面给出代码例子,让我们瞧瞧 Scala 如何实现方法多个返回值,并且作为对比我还会贴上 Perl, Ruby 和 C# 可以怎么实现多返回值。我是 Java 的惯用者,不过我一直都未否认,从语言层面 C# 比 Java 要显得优雅的多。用元组实现 Scala 方法多返回值:
1def foo = (100, "Unmi") //定义方法返回元组 2 3val (num, name) = foo //用元组模式去接收方法 foo 的结果 4println(num + ":" + name) //输出为 100:Unmi 5 6val values = foo //调用方法的结果直接给元组变量 7println(values._1 + ":"+ values._2) //输出同样是 100:Unmi
方法返回一个元组,里面可以组合任何多个的不同类型的返回值,调用时可以用元组变量或元组模式去接收方法的返回值,用元组模式的方式更好看些,也才能算作真正的多返回值。 Read More- 在 Scala 中当方法不需要接受参数时可定义成两种类型的方法
1. def width(): Int 空括号方法(empty-paren method)
2. def width: Int 无参数方法(parameterless method)
从语法上讲,Scala 在调用上面那种类型的方法时都可以统一用 obj.width 的方式,实际对于无参数方法是只能用 obj.width 的方式,而空括号方法,既可以用 obj.width 也可以用 obj.width() 的形式。
那么 Scala 在方法无须参数时是定义空括号方法还是无参数方法时有什么约定呢?当方法没有副作用(side effect)时,定义成无参数方法;当方法会产生副作用时,定义成空括号方法
那么又该如何识别方法是否有副作用呢?一般来说有副作用的地方会在于其结果类型是否为 Unit。如果某个函数不返回任何有用的值,也就是说如果返回类型为 Unit,那么这个函数唯一能产生的作用就只能是产生某种副作用,例如改变对象内部的某种状态,或是向控制台的输出等。有副作用的方法就像是数据库的存储过程(一般用于更新数据),无副作用的方法像是数据库的函数(一般用于查询得到数据)。 Read More - Scala 是构建在 JVM 上的静态类型的脚本语言,而脚本语言总是会有些约定来增强灵活性。灵活性可以让掌握了它的人如鱼得水,也会让初学者不知所措。比如说 Scala 为配合 DSL 在方法调用时有这么一条约定:
在明确了方法调用的接收者的情况下,若方法只有一个参数时,调用的时候就可以省略点及括号。如 “0 to 2”,实际完整调用是 “0.to(2)”。但 “println(2)” 不能写成 “println 10“”,因为未写出方法调用的接收者 Console,所以可以写成 “Console println 10”
到这里就要讲到 apply 和 update 方法相关的约定,描述的是直接在对象(对象)后直接加圆括号的代码的情况下,那就是:用括号传递给变量(对象)一个或多个参数时,Scala 会把它转换成对 apply 方法的调用;与此相似的,当对带有括号并包括一到若干参数的进行赋值时,编译器将使用对象的 update 方法对括号里的参数和等号右边的对象执行调用。
对上面那段话的解释可由下面几个例子得到很好的理解
1. theArray(0), 取数组的第一个元素的操作会转换成 theArray.apply(0) 操作,这也能解释为什么 Scala 数组取值不用中括号括下标的方式,因为它也是一次方法调用 Read More
在 Java 或者 Scala 的类中,super.foo() 这样的方法调用是静态绑定的,也就是说当你在代码中写下 super.foo() 的时候就能明确是调用它的父类的 foo() 方法。然而,如果是在特质中写下了 super.foo() 时,它的调用是动态绑定的。调用的实现奖在每一次特质被混入到具体类的时候才被决定。
确切的讲,特质的 super 调用与混入的次序很重要,参照下面的例子说话:1val queue = (new BasicIntQueue with Incrementing with Doubling)
直截的讲就是超靠近后面的特质越优先起作用。当你调用带混入的类的方法是,最右侧特质的方法首先被调用。如果那个方法调用了 super,它调用其左侧特质的方法。可以这么认为,Doubling 的 super 指向了 Incrementing,Incrementing 的 super 指向了 BasicIntQueue。
来看个完整的实例实际体验一把,如果要帮助理解,最好应该实际运行一下这个实例 Read More
我看了《Programming in Scala》一书,仍然对 Scala yield 关键字的理解不甚清楚。起初我以为 Scala yield 的与 Ruby 的 yield 是一样,Ruby 中 yield 是被传入代码块的占位符。Scala 中的 yield 关键字好像总是在 for 循环中用的. 下面一些例子可以帮助你更好的理解 yield 关键字。下面是摘自 《Programming in Scala》关于 yield 的解释:For each iteration of your for loop, yield generates a value which will be remembered. It's like the for loop has a buffer you can't see, and for each iteration of your for loop, another item is added to that buffer. When your for loop finishes running, it will return this collection of all the yielded values. The type of the collection that is returned is the same type that you were iterating over, so a Map yields a Map, a List yields a List, and so on. Also, note that the initial collection is not changed; the for/yield construct creates a new collection according to the algorithm you specify.
上面那段话的意义就是,for 循环中的 yield 会把当前的元素记下来,保存在集合中,循环结束后将返回该集合。Scala 中 for 循环是有返回值的。如果被循环的是 Map,返回的就是 Map,被循环的是 List,返回的就是 List,以此类推。 Read More- Scala 在方法里除了可用 assert() 方法像 Java 那样进行断言,还可以使用 ensuring() 方法在返回结果的分支的花括号同一行上进行断言。它们不同的是 assert 可以随意放在哪里对任何的 boolean 类型进行断言,而 ensuring 是用来对返回结果行断言的,所以它必须尾随返回结果处。 assert 和 ensuring 方法都是定方在 Predef 中的,所以可以直接写。
在 《Programming in Scala》一书中对 ensuring 使用的示例代码,会让人感到很费解的,并且对 ensuring 的解释也不多,只是说了 ensuring 中用 "_" 作为当前返回结果对象的占位符。在 《Programming in Scala》中 ensuring 示例代码是:1private def widen(w: Int): Element = 2 if(w <= width) 3 this 4 else { 5 val left = elem(' ', (w - width)/2, height) 6 var right = elem(' ', (w - width -left.width, height) 7 left beside this beside right 8 } ensuring (w <= _.width)
第一个让人一下不好理解的是方法定义第一行等号后没有加花括号,一般来说方法只包一条(行)语句时花括号可以省略,多行时虽然程序能够推断出该方法在何处解释,但人来阅读时却不容易把握方法代码在哪里结束,所以最好多行时用花括号括住函数代码。再说,如果在 Scala 控制台敲上面的代码,中间加回车的时候就会报错。 Read More - Tomcat 下日志文件 catalina.out 过大,几百兆或几个G,进而造成再也无法写入更多的日志内容,至使 Tomcat 无法处理请求。需然你可以在 $TOMCAT_HOME/logs 目录下看到有 catalina.2012-09-16.log 这样分日期的归档,但是主文件 catalina.out 却一直在膨胀。
你可以每次手工或定时(crontab/计划任务)清理 catalina.out 文件,或是规划好日志输出(终究也会有满的时候)。再就是有两种较好的解决方案去真正的切分 catalina.out 文件,让 catalina.out 只存有最新的日志。
一. 改用 Log4J 来输出 Tomcat 日志,借助 Log4J 的各种日志切分的功能。详情可参考: http://baalwolf.iteye.com/blog/1464093, http://tomcat.apache.org/tomcat-6.0-doc/logging.html。
二. Linux 下使用 cronolog 工具来切分 catalina.out
这里重点介绍这种方法,具体步骤如下: Read More - 还是在很久以前,作过一篇 用 AOP 来记录每个方法的执行时间(Spring 或直接 AspectJ), 其中例示了三种方法来拦截方法,用以监测方法调用时间它们分别是:
1. Spring 2.0 用 AspectJ 实现 AOP
2. Spring 通用的方法拦截
3. 直接用 AspectJ 实现
在这里再次使用 <aop:aspect-autoproxy/> 再 @Aspect 注解的方式来写个新的例子。原理与前面基本一致,只是在类里用 @Aspect, @Pointcut, @Before, @After, @Around, @AfterReturning, @AfterThrowing 来写拦截类。
局限仍然是必须通过 Spring 的 BeanFactory 获得的实例才能被拦截到,除非是在 Eclipse 里安装 AJDT 或是使用 Maven-AspectJ Plugin 来编译工程。
好,我们来看完整的例子,下面列出所有的项目文件,这是一个 Maven 的项目,所以从 pom.xml 开始。 Read More