前言:
本章要点:
- 类中的字段自动带有
setter、getter
方法 - 可以自定义
setter、getter
方法 - 用
@BeanProperty
注解来生成JavaBeans
的getXXX/setXXX
方法 - 每个类都有主构造器和辅助构造器
1.简单类和无参方法
- Scala类中必须初始化字段,方法默认是公有的
class Counter{
private var value = 0
def increment(){value +=1}
def current() = value
}
调用无参方法时可以不写圆括号
val myCounter = new Counter//或者 new Counter()
myCounter.increment()
myCounter.current
对于该值器方法(改变对象状态的方法)使用()
,而对于取值器方法(不改变对象状态的方法)可以不写()
。
2.带getter和setter的属性
Scala为每个组字段都提供setter、getter
方法
class Person{
var age = 0
}
age
的两个方法均是公有的,因它没有private
前缀。在Scala中,这两个方法分别叫做age和age_
。
在任何时候你都可以重新定义这两个方法
class Person{
private var age = 0 //注意此处使用的是private
def age = privateAge
def age_ = (newValue:Int){
if(newValue>privateAge) privateAge = newValue;
}
}
注意此处,该字段是私有的,则其getter和setter
方法也是私有的。
如果字段是val
,则其只有getter
如果你不需要这两个方法,则可以将字段声明为private[this]
3.只带getter的属性
class Massage{
val timeStamp = java.time.Instant.now
}
Scala会生成一个私有的fianl
字段和一个getter
方法,但是没有setter
此时需要一个属性,客户端不能随意改变,但是又可以通过某种方式修改。
class Counter{
private var value = 0
def increment (){value+=1}
def current = value //注意,声明中没有()
}
注意:对于getter
方法,你必须以不带括号的方式使用:
val n = myCounter.current //不可以用current()
4.对象私有字段
在Scala中,方法可以访问该类的所有对象的私有字段
class Counter{
private var value = 0
def increment (){value+=1}
def isLess(other : Counter) = value <other.value
}
之所以other,value合法,是因为other
也同样是Counter
对象。Scala允许我们定义更为严格的访问限制,通过private[this]
来实现private[this] var value = 0//此时访问someObiect.value不被允许
,此时Counter
只能访问当前对象的value
字段。
Scala还允许将访问权限赋予指定的类private[类名]
可以定义仅有指定类的方法访问给定的字段。
5.Bean属性
JavaBeans规范把Java属性定义为getFoo/setFoo
方法。在Scala中,当你将字段标注为@BeanProperty
时,这样的方法会自动生成。
class Person{
@BeanProperty var name:String = _
}
此时将会生成四个方法:name/name_和getName()/setName()
6.辅助构造器
Scala有任意多个构造器,一个主构造器,其他的全部都是辅助构造器。
辅助构造器:
- 名称为:this
- 每一个辅助构造器都必须以一个对先前已经定义的其他辅助构造器或者主构造器的调用开始
class Person{
private var name = ""
private var age = 0
def this(name:String){
this()//调用主构造器
this,name = name
}
def this(name:String,age :Int){
}
}
7.主构造器
主构造器的参数直接放在类名之后
class Person(val name:String,val age :Int){
}
- 主构造器的参数被编译为字段,其值被初始化成构造时传入参数。
- 主构造器会执行类定义中的所有语句。println也是主构造器的一部分
- 如果类名后面没有参数,则该类具备一个无参主构造器。
class Person(val name : String,private var age:Int)
这段代码将声明并初始化如下字段
val name:string
private var age:Int
构造参数也可以是普通的方法参数,不带var/val。这样的参数如何处理取决于他们在类中被如何使用。
- 不过不带val/var的参数至少被一个方法所使用,它将会被升格为字段。
class Person(name:String,age:Int){
def description = name +" is "+age+"years old"
}
//这段代码声明并初始化了不可变字段name,age,这两个字段都是私有对象,
//类似于这样的字段等同于private[this] val 的效果
- 否则,该参数将不会被保存为字段
如果想让主构造器变成私有的,则在类名后面加上关键字private
class Parson private(val age:Int){}
8.嵌套类
你几乎可以在任何语法结构中内嵌任何语法结构。
class Network{
class Member(val name:String){
val contacts = new ArrayBuffer[Member]
}
private val members = new ArrayBuffer[Member]
def join(name :String){
val m new Member(name)
member +=m
m
}
}
val chatter = new Network
val myFace = new Network
如上,每个实例都有自己的Member对象,但是这两个Member对象是不同的两个类,像把其中一个Member对象添加到另一个Member对象中是不被允许的。若想实现这种不被允许的功能,则可以:
- 将Mamber对象移到其它地方去,比如伴生对象中
object Network{
class Member(val name:String){
}
}
- 类型投影
Network#Member
,其含义是”任何Network的Member“
class Network{
class Member(val name:String){
val contacts = new ArrayBuffer[Network#Member]
}