二、Scala 类与对象
标签(空格分隔): Scala 学习笔记
/**
* Created by Sweeney on 2017/10/26.
*/
class CheckSumAccumulator {
private var sum = 0;
def add(b: Byte): Unit = {
sum += b
}
def checksum(): Int = {
return ~(sum & 0xFF) + 1
}
}
Scala 中定义类跟在 Java 中定义类区别不是很大,只是 Scala 中成员默认的访问级别就是 public,也就是说定义公有属性不用加 public 关键字。但是定义私有属性任然使用 private。
CheckSumAccumulator 类中定义了两个方法,Scala 里方法参数的一个重要特性就是她们都是 val。如果想在方法里给参数重新赋值,就会报错。
CheckSumAccumulator 中的方法虽然没有问题,但是代码不够简洁。如果方法中没有发现任何显式的返回语句,Scala 方法将返回方法中最后一次计算得到的值。方法的推荐风格是尽量避免使用返回语句。
所以可以改造成:
/**
* Created by Sweeney on 2017/10/26.
*/
class CheckSumAccumulator {
private var sum = 0;
def add(b: Byte): Unit = sum += b
def checksum(): Int = ~(sum & 0xFF) + 1
}
对于类中的 add 方法那样的结果类型为 Unit 的方法来说,执行的目的就是为了它的副作用。通常我们定义副作用为能够改变方法之外的某处状态或执行 I/O 活动的方法。所以像 add 这样仅仅为了副作用而执行的方法有另一种表达方式:去掉结果类型和等号,把方法放到花括号内。例如:
/**
* Created by Sweeney on 2017/10/26.
*/
class CheckSumAccumulator {
private var sum = 0;
def add(b: Byte) {
sum += b
}
def checksum(): Int = ~(sum & 0xFF) + 1
}
Singleton 对象
/**
* Created by Sweeney on 2017/10/26.
*/
class CheckSumAccumulator {
private var sum = 0;
def add(b: Byte) {
sum += b
}
def checksum(): Int = ~(sum & 0xFF) + 1
}
object CheckSumAccumulator {
import collection.mutable.Map
private val cache = Map[String, Int]()
def calculate(s: String): Int = {
if (cache.contains(s))
cache(s)
else {
val acc = new CheckSumAccumulator
for (c <- s)
acc.add(c.toByte)
val cs = acc.checksum()
cache += (s -> cs)
cs
}
}
}
Scala 中不能定义静态成员,而是代之以定义单例对象,除了用 object 关键字替代了 class 关键字以外,单例对象的定义与类定义一致。
当单例对象与某个类共享同一个名称时,它就被称为这个类的伴生对象,类和它的伴生对象必须定义在同一个文件里。类被称为是这个单例对象的伴生类,类和它的伴生对象可以互相访问其私有成员。
定义单例对象并没有定义类型,如果只有单例对象的定义,就不能定义单例对象的变量。因为类型是由单例对象的伴生类定义的。然而单例对象扩展了父类并可以混入特质。因此,可以使用类型调用单例对象的方法,或者用类型的实例变量指代单例对象,并把它传递给需要类型参数的方法。
类和单例对象间的差别是,单例对象不带参数,而类可以。因为单例对象不是用 new 关键字实例化的,所以没机会传递给它实例化参数。每个单例对象都被实现为虚构类的实例,并指向静态的变量,因此他们与 Java 静态类有着相同的初始化语义。单例对象在第一次被访问的时候才会被初始化。
不与伴生类共享名称的单例对象被称为独立对象。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于