Java 中 静态成员是对应类的,所以既可以通过对象名,也可以通过类名访问,但不能访问非静态方法或变量;位于“数据区”,无论多少个对象该变量在内存中都只有一份;
Java中非静态成员是对应对象的,每个对象都会有一个,所以只能通过对象名引用;位于“堆空间”,每new一个对象创建一份,因此有多少个对象该变量在内存就有多少份;
scala中没有静态方法和属性,全部由singleton object(单例对象)来替代;
******************************
java的interface只定义方法名称和参数列表,不能定义方法体; 实现接口用implement;trait可以看作有方法实现和字段的interface;代表一类事物的特性
Scala 中trait则可以定义方法体,即 可以包含方法的接口;实现trait 用extends;scala可以在一个class实例化的时候混合进一个trait, 并通过用with 对其进行包装;
*********************************
val evenNumbers = List(2, 4, 6, 8, 10)
evenNumbers.foldLeft(0) { (a: Int, b:Int) => a + b }
可以利用 Scala 的参数类型推测功能 将上面操作简化为:evenNumbers.foldLeft(0) { (a, b) => a + b } 甚至可以简化为 evenNumbers.foldLeft(0) { _ + _ }
********************************************
模式匹配的基本思想就是试图对一个值进行多种模式的匹配,并且在匹配的同时将匹配值拆分成若干子项,最后对匹配值与其子项执行某些代码;
case classes
- 编译器为case class生成一个同名的对象构造器(Factory Method),也就是你可以使用 Var(“x”) 来创建一个类的实例,而无需使用new Var(“x”).-->可以省略 new 关键字
- Scala prefixes all the parameters with val,
- A companion object is created with the appropriate apply method
- The compiler adds a method called unapply
- Scala编译器为case class的构造函数的参数创建以参数名为名称的属性,比如Val的类的参数name:String 可以直接通过 .name访问;.-->即自动添加 getter 方法
- 编译器为case class 构造了更自然的toString,hashCode和equals实现,它们会递归打印,比较case class的参数属性;-->这些实现可以按照值区别类实例是否相等,从而方便进行 模式匹配
- Scala编译器为case class添加了一个Copy方法,这个copy方法可以用来构造类对象的一个可以修改的拷贝。这对于使用已有的对象构造一个新实例非常方便,你只要修新创建实例的某些参数即可。
- eg
这个程序的目标是处理一些由整数常量、变量和加号组成的简单的算数表达式,例如1 + 2 和 (x + x ) + (7 + y )。
abstract class Treecase class Sum(l: Tree, r: Tree) extends Treecase class Var(n: String) extends Treecase class Const(v: Int) extends Tree我们实际上定义了三个条件类 Sum ,Var 和 Const 。表示我们算数表达式的数据类型.
下面给他们定义对应的操作。我们将会首先编写一个在上下文中下计算表达式的函数。这里的上下文指的是变量与值的绑定关系。例如表达式x+1在x=5上下文中应该得出结果6。
type Environment = String => Int现在我们可以开始定义求值函数了。
def eval(t: Tree, env: Environment): Int = t match {
case Sum(l, r) => eval(l, env) + eval(r, env)
case Var(n) => env(n)
case Const(v) => v
}
********************************************
Scala的Option类型可以避免这种情况,因此Scala应用推荐使用Option类型来代表一些可选值。使用Option类型,读者一眼就可以看出这种类型的值可能为None。
在写模式匹配时,为保证可选项覆盖了全部的可能性,这时可以为基类添加上Sealed关键字,这样你就只需要关心已经定义的子类,如果可选项不去全,编译器会自动警告。
**********************************************
case class 的优点
- match是表达式,不是语句,所以是有返回值的,
- 在模式中使用变量可能会与常量冲突,因此变量要以小写字母开始。如果有常量是小写字母开头的,那么需要用反引号将常量名包起来
case class 的用处:
- 用于替换 tuples
- val p = ("qh",20) // p._1 = "qh", p._2 = 20;好处是简洁,但无意义
- case class person(name:String, age:Int)
val p = person("qh",20) // p.name = "qh", p.age = 20; 好处是有名字,自说明,可读性强
- val p = ("qh",20) // p._1 = "qh", p._2 = 20;好处是简洁,但无意义