本文链接: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不同,但可表达的意义相近。