本文链接:Scala学习(一)——类、对象和变量
简介
Scala是一种基于JVM的语言,但是兼顾了Java的面向对象特性和函数式编程。因为不像Java那样那么需要兼顾向后兼容性,Scala的活力比Java要高出许多,语言特性也丰富许多。更好的泛型、更方便的回调、更简单的集合操作。
因为函数式编程和以前的面向对象编程以及面向过程编程的思路都很有差异,一步登天是不可能的,所以我决定以Java为基石,从Scala的语法特性学起,以求从语法特性中获得语言特性,再经过练习使用来进一步巩固对Scala的理解。
常量,变量和函数
先看写法:
1 2 3 4 5 6 |
val A: Int = 7 var B: String = "123" def C(p: Int): Unit = { // Unit类型类似Java中的void println(p) } B = "456" |
用val
定义的是常量,用var
定义的是变量。名称在前,类型在后,中间有一个冒号。一般来说Scala中的常量和变量都是在定义时就被初始化了的。Scala编写过程中有一个特点,那就是尽量使用常量。
如果可以猜出类型,那么不需要显式指定类型:
1 2 3 4 5 |
val A = 7 // Int var B = "123" // String val C = 1.0 // Double var D = 2f // Float val E = 0l // Long |
用def
定义的是函数,之所以放在这里讲,是说函数和常量变量性质很类似,可以看做一个对象:
1 |
val D: Int => Unit = C |
函数的定义同样是使用了类型在后的写法,参数列表最后的冒号后的类型是返回类型:
1 2 3 |
def C(p: Int): Int = { return p } |
基本类型
Scala比Java隔年面向对象,Scala取消了基本类型。常用的整数,浮点数,布尔值也都是类。这里先不需要考虑运行效率和编译成字节码后的实现方式,因为实际上这些类型Scala编译器都会进行优化,将其变成Java的基本类型的。
其他类型
作为一个面向对象语言,类和对象是Java的基本元素。Scala继承了这一特性,下面来对比一下Scala和Java中的类:
概念 | Java | Scala |
---|---|---|
类 | class |
class |
接口 | interface |
可用trait 表达 |
特征 | – | trait |
枚举 | enum |
– |
标注 | @interface |
通过继承Annotation 类实现 |
独立对象 | 可以通过单例模式实现 | object |
包对象 | – | packet object |
可以看出,两者大体相同。不过Scala中添加了更多要素,下面大概说明一下这些要素的编写方法。
类
基本写法:
1 2 3 4 5 6 7 |
class AClass { val A = 3.0 private var B = 0l // private表示其他类(包括子类)不可访问 def X(a: Int): Unit = { println(a) } } |
Scala中没有public
修饰符,所有未加修饰符的都是公有。
类可继承其他类:
1 2 3 4 |
class BClass extends AClass { override val A = 1.0 // override关键字表示覆盖,此时类型不可改变 val B = 4 } |
也可以使用某个特征:
1 2 3 |
class CClass extends ATrait { override val C = 1.0 // override关键词可省略,实现了特征中的常量 } |
可以使用多个特征:
1 2 3 4 |
class DClass extends ATrait with BTrait { override val C = 1.0 override val D = 1.0 } |
可以同时使用继承类和特征:
1 2 3 4 |
class EClass extends AClass with ATrait with BTrait { override val C = 1.0 override val D = 1.0 } |
可以设置抽象类,不可被实例化:
1 2 3 4 5 |
abstract class FClass { val E: Int // 只有抽象类型中的变量,常量和函数可以不初始化 var F: Int def Z(): Unit } |
可以设置终类,不能再被继承:
1 2 3 |
final class GClass { val G = "123" } |
总结一下:Scala中的类和Java中的类比较类似,可以单继承其他类,多继承特征(Java中是接口),也可以设置为抽象类或者终类。
特征
特征(Trait
)是Scala中的重要概念,和Java中的接口相比,特征的要求相对较低,这给编程带来了较大的自由度,但是与之而来的是一些问题,比如多继承(虽然Java8中default函数的出现使得Java也出现了这种问题)等等。但在本文中,主要讨论写法之间的差异,不会列举出所有可能出现的问题。
基本写法:
1 2 3 4 5 6 7 |
trait ATrait { def X(a: Int): Unit val C: Double // 和Java的Interface不同,Trait可以加成员 def Y(a: Double): Int = { // 变量和已实现的函数 return a.toInt() } } |
继承其他特征:
1 2 3 |
trait BTrait extends ATrait { val D: Double } |
继承多个特征:
1 2 3 |
trait CTrait extends ATrait with BTrait { // Nothing } |
继承类:
1 2 3 |
trait DTrait extends AClass { // Nothing } |
继承类和特征:
1 2 3 |
trait ETrait extends AClass with ATrait { // Nothing } |
注意:虽然特征可以从类中继承出来,但是最好不要这样写。因为Scala中一个类只能有一个唯一的父类,包括直接的父类和通过特征获得的间接的父类,从类中继承出特征很容易使得编译不通过。实际使用中特征也只会从特征中继承出来。
对象
和Java一样,使用new
可以从类名中实例化出对象来。
Scala还提供了一种直接定义单例对象的方式:
1 2 3 4 5 6 |
object AObject { val A: Int = 0 def B(a: Int) = { return a } } |
调用时,可以直接使用,也可以通过变量使用,效果是一样的:
1 2 3 |
AObject.B(1) // 注意这不是静态调用,Scala里面不存在静态 val aobj = AObject aobj.B(2) |
总结
Scala包含了和其他面向对象语言相同的基本功能:类、对象和变量,但是理念稍有不同。首先,函数可以看做对象,储存在变量里(函数式);然后,Scala取消了静态,而是使用单例对象(面向对象);最后,使用特征而不是接口使得Scala更加灵活。
すごい
すごい