17Aug/104
Scala笔记2
最近几天杂事很多,导致那本薄薄的Scala至今未看完……今天先来接一下Scala笔记2
- Scala的访问控制机制和Java有别。有些许的概念不同而且能够做到更加细粒度的控制。Scala默认访问修饰为public,Java则是微妙的default。Scala中的protected则比Java更小气,它只对自己和派生类可见,同包下的其它类无法访问,而且类也只能访问自己的基类中的protected成员,无法访问继承同样基类的其余派生类中的基类protected成员。Scala对细粒度访问控制体现在private和protected修饰可以通过方括号指定额外的报名或类名来赋权。
- Scala中调用方法传递参数时,可以选择使用圆括号和花括号,它们是等价的。花括号这个语法糖结合curry可以使抠腚鹅们写出看上去更爽的代码,比如自制while循环原语,见下面的代码清单。
object MakeYourWhile { def main(args: Array[String]) { var i = 0 myWhile(i < 4) { //第一个参数使用圆括号,第二个使用花括号 i += 1 println(i) // 输出了1 2 3 4 } } // 定义一个myWhile方法对象,参数是一个返回Boolean的方法和一个返回Unit的方法 def myWhile(p: => Boolean)(f: => Unit) { if (p) { f myWhile(p)(f) } } } - Scala没有static修饰符,它用object为类添加类级别的成员。其实用object声明的类就是一个单例对象,抠腚鹅们可以像使用静态成员一样通过类名调用它们。同名的class和object声明被称为独立对象(class)和伴生对象(object),它们被认为是同一个类,可以互相访问彼此的private成员。
- Scala拥有严格而灵活的泛型定义(一个让人有点头晕却又强大的特性)。Scala可以显示的定义类型转换是否支持协变和逆变,同时还可以限定类型参数在继承关系中的上下届,下面的代码清单折腾了这些特性。
object SoManyCar { def main(args: Array[String]) { val chevrolet0 = new Something0[Chevrolet] val car0: Something0[Car] = chevrolet0 // 编译错误 不允许把派生类容器赋给基类 val chevrolet1 = new Something1[Chevrolet] val car1: Something1[Car] = chevrolet1 // 不报错 因为+T的类型声明告诉Scala支持协变 val car2 = new Something2[Car] val chevrolet2: Something2[Chevrolet] = car2 // 这都行?!-T的类型声明让Scala支持逆变 Java可不带这么玩的 val car3 = new Something3[Car] // 编译错误 T <: Chevrolet声明了类型下界为Chevrolet 所以不允许Chevrolet的基类Car val chevrolet3 = new Something3[Chevrolet] val cruze3 = new Something3[Cruze] val car4 = new Something4[Car] val chevrolet4 = new Something4[Chevrolet] val cruze4 = new Something4[Cruze] // 编译错误 T >: Chevrolet声明了类型上界为Chevrolet 所以不允许Chevrolet的派生类Cruze } } class Car {} // 唔 这是一辆车 class Chevrolet extends Car {} // 嗯 这是一辆雪佛兰 class Cruze extends Chevrolet {} // 好了 这是一辆科鲁兹 class Something0[T] {} // 普通 class Something1[+T] {} // 协变 class Something2[-T] {} // 逆变 class Something3[T <: Chevrolet] // 限定下界 class Something4[T >: Chevrolet] // 限定上届 - trait,Scala中相当让人头晕却又相当神奇而强大的特性。trait,意指特质,在Scala中它类似带有部分实现的接口(编译的时候其实就是被处理成了一个interface和一个helper类)。对于trait,混入这个概念比继承更清晰。一个类可以被混入叠加多种特质,更进一步,trait甚至还可以只叠加到一个特定对象上,通过在运行时使用with关键字来创建新对象的方法。下面的代码清单尝试演示trait的特性,同时展示了其中特殊的super调用概念。
object TraitTest { def main(args: Array[String]) { val people1 = new People with Cruze // 有科鲁兹的路人甲 val people2 = new People with Cruze with Sagitar // 有科鲁兹又有速腾的路人乙 // 在people2中Sagitar的super调用了Cruze中的方法 而Cruze中的super调用又跑到了它extends的Car上 println(people1 haveCar) println(people2 haveCar) } } class People { } abstract trait Car { def haveCar(): List[String] = List[String]() // haveCar返回一个空数组 } trait Cruze extends Car { override def haveCar(): List[String] = "CRUZE" :: super.haveCar() // 俺有一辆科鲁兹 // 其中的super调用实际上是延迟绑定的 在运行时被指向到当前trait链左边的trait } trait Sagitar extends Car { override def haveCar(): List[String] = "SAGITAR" :: super.haveCar() // 俺有一辆速腾 } - Scala可自定义隐式类型转换,通过implicit关键字定义一个转换对象的函数来支持自定义隐式类型转换。这个特性也是被设计用来支持在Scala上构建DSL的。下面从图灵那本Scala的书中抄了一段代码过来演示……
object ImplicitTest { // 一个将Int隐式转换为DateHelper的转型方法 implicit def int2DateHelper(number: Int) = new DateHelper(number) val ago = "ago" val from_now = "from_now" def main(args: Array[String]) { println(2 days ago) println(5 days from_now) } } import java.util.{Date, Calendar} // 哈 可以在代码中间import class DateHelper(number: Int) { def days(when: String): Date = { val date = Calendar.getInstance when match { case "ago" => date.add(Calendar.DAY_OF_MONTH, -number) case "from_now" => date.add(Calendar.DAY_OF_MONTH, number) case _ => date } date.getTime } }
好了,2就2到这儿了,未完待续……
关于MySQL事务隔离级别 »
« SFINAE
August 18th, 2010 - 01:11
你这不逼着哥找一张宽一点的皮么~
August 18th, 2010 - 09:34
这张够宽了……起码哥公司电脑还是1280*1024的分辨率
另外我就知道你果然会来加read more的tag……
August 18th, 2010 - 13:05
飞飞威武啊!
1280×1024是个啥分辨率?
August 18th, 2010 - 15:26
17′ LCD