本文链接:Scala学习(二)——成员,方法和构造方法
简介
上一章中其实也可以看到,Scala和Java类似,在类内直接定义的变量、方法即是成员变量和方法。但Scala中的构造方法和Java稍微有些不同。
成员
首先可以像Java那样直接定义成员:
| 1 2 3 4 5 | class AClass {   val a = 1   val b = 0.1   var v = 7l } | 
也可以设置访问级别,默认是公有,没有public关键字(可以当变量名使用):
| 1 2 3 4 5 | class BClass {   private val a = 1   protected val b = 0.1   var public = 7l } | 
成员方法也是类似的:
| 1 2 3 4 5 6 7 8 9 10 11 | class CClass {   private def a(): Unit = {     println("a")   }   protected def b: Int = {     return 0.1   }   def public(i: Int): Int = {     return i + 1   } } | 
值得注意的是,Java中成员变量和方法名称可以重复,即可以存在同名的方法和变量,但是Scala中不可以。
构造方法
Scala中构造函数和类定义是联系在一起的:
| 1 2 3 4 5 6 7 | class DClass(aInput: Int) {   val d = aInput  // 直接使用参数   init()          // 在类定义里的语句会在构造时运行   def init(): Unit = {     println(aInput)  // 这里也可以使用   } } | 
如果在构造函数的参数中加入val或者var,就可以直接赋予参数成员变量的含义。比如我们要定义一个二维向量类,那么可以这么写:
| 1 2 3 | class Vec2(val x: Int, val y: Int) {   //... } | 
以后可以使用
| 1 2 | val a = new Vec2(1, 2) println(a.x) | 
的方式来访问这两个成员,就和使用在类本体内定义的成员一样。
如果要继承定义了构造函数的类,就需要在继承时显式调用之:
| 1 | class EClass(a: Int) extends DClass(a) { | 
或者
| 1 | class EClass extends DClass(1) { | 
可以在参数列表前加上private和protected来限定构造函数的访问权限:
| 1 | class DClass protected(aInput: Int) { | 
辅助构造方法
如果需要使用参数差异很大的构造方法,可以使用辅助构造方法:
| 1 2 3 4 5 | class DClass(aInput: Int) {   def this(b: Double) = {     this(b.toInt)   // 辅助构造方法的第一句必须是调用主构造方法   } } | 
然而,辅助构造方法并没有主构造方法转化参数为成员变量的能力。
方法
用def关键字可以定义方法,方法以关键字def开始,然后是方法名,其后是关键字列表,再其后是返回值类型,最后是=和函数体:
| 1 2 3 | def method(a: Int, b: Double): String = {   return a.toString + " " + b.toString } | 
调用方法:
| 1 2 3 | method(0, 0.1) method(a = 0, b = 0.1)  // 可以用“参数名 = 值”的方式调用 method(b = 0.1, a = 0)  // 以此方式调用,顺序不限 | 
方法可以使用默认参数,默认参数不限制为最后几个值,可以出现在任意位置:
| 1 2 3 4 5 6 7 8 9 | def method(a: Int = 1, b: Double): String = {   return a.toString + " " + b.toString } def method2(a: Int, b: Double = 0.1): String = {   return a.toString + " " + b.toString } method(1, 0.1)  // 普通调用 method(b = 0.1) // 使用默认参数 method2(1)      // 使用默认参数 | 
另外,无参函数可以在定义时不写括号:
| 1 2 3 | def method3: Int = {   return 1 } | 
这样,调用时也不能写括号(区分一下,如果定义时写了括号,那么此时可写可不写,按照编码规范需要写):
| 1 | val n = method3 | 
既然提供了这一特性,那么就有必要区分一下是否写括号。Scala的意图是,如果方法没有副作用(改变状态,输入输出等等),那么就不需要写括号,比如get函数之类的。如果有副作用,那么必须写括号,比如close()。当然这只是个约定,编译器并不会检查方法中实际做了什么的。
总结
Scala中的方法调用和Java还是很类似,不过增加了默认参数的设计。构造函数和Java不同,但可表达的意义相近。