两年前阅读《scala编程》(Programming in Scala)一书时做的一些零碎笔记。
注:当时PIS这本书还是第一版,里面是基于scala2.7的,有些类已经过时,比如RichString已被StringOps替代。
1) package名字可以与实际文件路径不同
2) class前面加public在eclipse会提示错误? 多此一举
3) 定义object 名字大写还是小写? scala源代码里有很多都是小写,但其他开源代码里都和class一样首字母大写
是否有特定说明?
4) class A private(str:String) 注意,这个构造函数中的变量没有声明为val或者var,
这种情况下,会生成private的setter和getter
如果 class A private(val str:String) 则会生成public的getter和setter,这是一个细节点
更新: 注意,var才有setter方法,方法名称为 xxx_$eq(xxx)
,val的只有getter,没有setter
5) i++或者++i 在scala中不起作用,必须用 i=i+1 或者 i+=1
6) scala把二元操作表达式 1 -> "A"
转换为 (1).->("A")
,任何对象都可以调->方法,并返回键值对的二元组(tuple)
任何对象都能调用->方法的机制为隐式转换。
7) RichString自2.7x之后已经被改为了scala.collection.immutable.StringOps 原先是scala.runtime包下
真坑爹,居然不能兼容。见:http://www.scala-lang.org/node/9901
8) p24,不能直接写 println 10 (此时小括号不可省), 但可以写成 Console println 10,需要注明方法的所有者。
9) p27,List不支持append操作,变通的方式是newEle::myList然后再reverse myList
10) p28, 元组(tuple)的索引是由1开始,而非0开始。
11) Arry,List,Set等,在创建一个集合时范型类型 [Type]
都可省,
val arr = Array("A","B");
val list = List(1,2,3)
12) 可变和不可变集合的 += 操作含义不同
不可变 imSet += newEle 等价于 imSet = imSet + newEle
可变 mSet += newEle 等价于 mSet.+=(newEle) 是方法而非操作符
13) p288 import可以很细粒度,只导入某个方法, import A.method
14) p266 抽象成员不许要加abstract,只要不赋值便是抽象的,但注意val与var的区别(var除了getter还有setter)
hongjiang@whj /tmp/dd % cat A.scala
abstract class A { var a:Int }
hongjiang@whj /tmp/dd % javap A
Compiled from "A.scala"
public abstract class A extends java.lang.Object
implements scala.ScalaObject{
public abstract int a();
public abstract void a_$eq(int); // var成员有赋值的setter方法
public A();
}
而 val则没有 setter方法。
抽象var,实际上也是抽象了getter/setter,并没有一个真正的var成员。
15) p418 给 this起别名
class A {self => // 对A.this的别名,这里可以随意用什么变量名,比如outer, a都可以
class B {
// self is the enclosing A, synonymous for A.this
}
}
16) p269 1) 预初始化字段,-> 不仅限于匿名类。2) lazy修饰。 TODO 这个地方需要展开。
17) p274 抽象类型,type SuitableFood <: Food 定义所有Food的子类。 <: 表示上界
18) p254 协变与逆变。 trait Queue[ +T ] {}
表示为协变
比如 S继承于T,则 Queue[S]
也继承于 Queue[T]
,
而逆变用 Queue[-T]
表示,与上面正相反, Queue[T]
将继承于 Queue[S]
19) p256 与java不同,scala中的数组不是协变的。
需要与java遗留方法交互时,可以将T类型数组造型为任意T的超类型数组
val a1 = Array("abc");
val a2:Array[Object] = a1.asInstanceOf[Array[Object]]
20) 混入Ordered特质(trait),则可以对对象用 <,>,<=,>=来做比较。
21) 元组中的类型不一致,不可迭代。
22) scala中的方法参数都是val,不可被重新赋值(不可变).
23) p135 scala中的相等操作“==”被设计为对类型表达透明,即对值类型和引用类型不像java区分
对引用类型==被视为继承自Object的equals方法的别名。
若有需要用java中的==场景,则使用 AnyRef.eq
方法。x eq y
是java中的 x==y
==
方法在Any中被定义为final的。
24) p379 存在类型,java中的Iterator<?>
在scala中可写为:Iterator[T] forSome {type T}
java中的Iterator<? extends Component>
可写为:
Iterator[T] forSome {type T <: Component}
表达形式为: type forSome{ declarations}
它可以缩写,比如:
Iterator[T] forSome {type T}
可简写为: Iterator[_]
Iterator[T] forSome {type T <: Component }
可简写为: Iterator[ _ <: Component ]
25) p375 注释
@SerialVersionUID(1234L)
@serializable
@throws(classOf[IOException])
26) p217 若需要对一个List不断加元素,可考虑用ListBuffer
listBuffer += newEle
// 加在后边。
3 +: myListBuf
// 元素加在前边。
27) scala2.9之后 Application
被 @deprecated
,用App
替代
28) scala2.8 @tailrec
该注释用来检查方法是否可用tail recursion来优化
29) 当函数使用return 返回对象时,必须声明函数的返回类型,不能省略
谢谢你的总结 但第21点 tuple是可以迭代的 因为case class 和 tuple 都是extends Product. 而 product 有 productIterator方法会返回一个Iterator[Any].
嗯,https://hongjiang.info/tuple-iterator/