class
Scala类使用class关键字定义,是对象的模板或者蓝图:
class Calculator {
val brand: String = "HP"
def add(m: Int, n: Int): Int = m + n
}
val calc = new Calculator //>
calc.add(3, 2) //> res0: Int = 5
calc.brand //> res1: String = HP
上例中使用val定义类的域,使用def定义类的方法,方法只是可以访问类实例状态的函数。
Methods are just functions that can access the state of the class.
构造器
不像Java中有特殊的构造方法,scala没有,在类中,方法定义之外的代码就是构造器,用于初始化对象的状态。
class Calculator(brand: String) {
/**
* A constructor.
*/
val color: String = if (brand == "TI") {
"blue"
} else if (brand == "HP") {
"black"
} else {
"white"
}
// An instance method.
def add(m: Int, n: Int): Int = m + n
}
构造器的参数在类名后面定义,使用new关键字创建类的实例:
val calc = new Calculator("HP")
calc.color
case class
case类是一种特殊的类,用于match的模式匹配,实例化时不需要使用new关键字。
case class Status(status:String)
val s1 = Status("Finish")
val s2 = Status("Running")
类继承
class ScientificCalculator(brand: String) extends Calculator(brand) {
def log(m: Double, base: Double) = math.log(m) / math.log(base)
}
覆盖基类方法:
class EvenMoreScientificCalculator(brand: String) extends ScientificCalculator(brand) {
def log(m: Int): Double = log(m, math.exp(1))
}
如果只想在类中定义方法,不提供实现,使用抽象类:
abstract class Shape {
def getArea(): Int // subclass should define this
}
class Circle(r: Int) extends Shape {
def getArea(): Int = { r * r * 3 }
}
抽象类不能被实例化。
Trait
特质Trait定义一组域和方法,可以被扩展或者混入到类中。
traits are collections of fields and behaviors that you can extend or mixin to your classes.
Trait类似与Java中的接口,但是Trait可以提供方法实现,更像是Java中的抽象类,但是类可以同时混入多个Trait(而Java只支持单继承)。
trait Car {
val brand: String
}
trait Shiny {
val shineRefraction: Int
}
扩展Trait:
class BMW extends Car {
val brand = "BMW"
}
使用with扩展多个trait:
class BMW extends Car with Shiny {
val brand = "BMW"
val shineRefraction = 12
}
多个with:
trait Shap {
val af: Int
}
class BMW extends Car with Shiny with Shap {
val brand = "BMW"
val shineRefraction = 12
val af = 9
}
一般,with被成为混入(mixin),而不是继承或扩展。另外,可以在实例化的时候才混入Trait:
class BMW extends Car with Shiny {
val brand = "BMW"
val shineRefraction = 12
}
val bmw = new BMW with Shap{
val af = 10
}
Trait or 抽象类:
两者的选择有时候很难,但是有一些经验可以供参考:
- 尽量使用trait,因为一个类只能集成一个class,但是可以mixin多个trait
- 如果需要构造参数,只能使用抽象类,因为trait的构造函数不能接收参数。
可以参考一下一些文章:
1) stackoverflow:Scala traits vs abstract classes
2) Difference between Abstract Class and Trait
3) Programming in Scala: To trait, or not to trait?
Types 泛型
scala中的泛型(Java中的说法)使用[]来表达,类似与Java的<>。
泛型类
trait Cache[K, V] {
def get(key: K): V
def put(key: K, value: V)
def delete(key: K)
}
泛型方法
在方法名后面使用[]表示(Java中在方法名之前使用<>表示)
def remove[K](key: K)