类的声明
scala中类的定义方式和java类似,通过class关键字来声明。
class Person(var age:Int)
构造器
类中可以有多个constructor(构造器),但只能有一个主构造器,可以有多个辅助构造器。直接在类后面声明成员变量,就会产生以该变量为参数的主构造器。使用new来创建实例的时候,强制传入对应参数。
val peter = new Person(12) //强制输入age参数
如果没有将主构造器参数放于类之后,则默认生成一个没有参数的主构造器。在scala中调用无参方法时,可以写圆括号,也可以不写,如果想强制使用无括号的调用方式,只需在无参方法声明的时候不写圆括号即可。
class Person {
var age:Int = _ // 必须初始化,Int类型默认初始化为0
}
// 调用无参主构造器,不需要加圆括号
val peter = new Person
// 也可以加上圆括号
val peter = new Person()
println(peter.age) // 输出0
还可以加@BeanProperty注解,在类中为成员变量自动生成getter和setter方法
class Person(@BeanProperty var age:Int)
val peter = new Person(12)
println(peter.getAge) // 为age自动生成getter方法
实例,成员变量
从上面的例子中,还可以学习到通过new来创建一个实例以及声明成员变量的写法。
scala中通过var来声明变量,通过val声明只读变量,与java不同,变量声明的范式是先写变量名,再写变量类型,这点与go语言一样。
在antlr4中对该文法的定义如下
classParam
: annotation* modifier* ('val' | 'var')? Id ':' paramType ('=' expr)?
;
内部类
相比其他高级语言,scala自由度很高,几乎可以在任何语法结构中嵌套任何语法结构,比如在类中嵌套类,在方法中嵌套类等。举个内部类的例子。
class Person(var age:Int, var name:String) {
class Wallet(var money:Double)
}
val peter = new Person(20, "Peter")
val wallet = new perter.Wallet(10)
但是,不同实例的内部类是不一样的,比如
class Person(var age:Int, var name:String) {
class Wallet(var money:Double)
def steal(wallet:Wallet) {
val money = wallet.money
wallet.money = 0
money
}
}
val peter = new Person(30, "Peter")
val wallet = new peter.Wallet(10)
val thief = new Person(23, "Thief")
thief.steal(wallet) // 错误,提示需要传入thief.Wallet类型
如果这样写,那么该小偷只能偷其他小偷的钱包,显然不符合他的本意,怎样修改呢?scala有一种机制叫类型投影,通过#标识。比如Person#Wallet的含义表示任意Person的Wallet,修改如下
class Person(var age:Int, var name:String) {
class Wallet(var money:Double)
def steal(wallet:Person#Wallet) {
val money = wallet.money
wallet.money = 0
money
}
}
val peter = new Person(30, "Peter")
val wallet = new peter.Wallet(10)
val thief = new Person(23, "Thief")
thief.steal(wallet) // 正确