Scala系列:类
简单类和无参方法:
1 class Counter { 2 private var value = 0; //必须初始化字段 3 def increment() = value += 1 //方法默认是公有的 4 def current = value 5 }
使用:
1 val counter1 = new Counter // 或 new Counter() 2 // 类定义方法是带了(),调用时可带,也可不带 3 counter1.increment 4 counter1.increment() 5 println(counter1.current) 6 println(counter1.current()) // error: 类定义方法时没带(),调用时也不能带
推荐的风格是:改值的方法带();取值的方法不带(),定义时不带便可强制取值风格。
Setter和Getter
1 class Person { 2 var age = 0; 3 }
对于属性age隐式的生成了age()和age_=(age: Int)方法。如果属性带private,则生成的方法也带private;如果属性不带private,则生成的方法为public。
如果属性为val,则只生成get方法。
如果禁用生成隐式的方法,使用private[this]声明。这样只能访问实例自身的属性,不能访问其它实例的属性,即对象私有成员。
注:不能实现只有Setter,没有Getter的属性。想实现,只能用其它名称了。
显式定义age()和age_=(age: Int)方法:
1 class Person { 2 private var _age = 0; // 变成私有并改名 3 4 def age = this._age; 5 def age_=(_age: Int) { 6 this._age = _age; 7 } 8 }
生成的java代码实际上生成了四个方法:显式定义的两个,改名后变量隐式生成的(private)
为什么要改名?不改名无法区分方法名和属性名,而且出现方法定义两次错误
Java Bean规范
生成类似Java Bean的setAge和getAge方法,只需要添加一个注解:@BeanProperty
1 class Person { 2 @BeanProperty 3 var age = 0; 4 }
上面的例子除了隐式生成了age()和age_=(age:Int)方法外,另外生成Java Bean风格的getAge()和setAge(age:Int)方法
主构造方法:
和类定义交织在一起:
参数被编译成字体;
主构造方法会执行类定义中的所有语句;
构造方法中参数不带val也不带var,只有被一个以上方法调用时才会提升为字段。类似于private[this] val效果
1 class Person(@BeanProperty var age: Int) { 2 }
会生成一个带age:Int参数的构造函数;
age()和age_=(age:Int)方法
getAge()和setAge(age:Int)方法
一个类如果没有显式定义主构造方法,会隐式生成一个无参不做任何操作的主构造方法。
辅助构造方法:
辅助构造方法的名称为this;
辅助构造方法每一行必须是调用构造方法(主构造方法或其它辅助构造方法)
def this(age:Int) {
this()
_age = age
}
嵌套类:
内部类与外部类实例相关联
1 class Network { 2 class Member(val name: String) { 3 val contacts = new ArrayBuffer[Member] 4 } 5 private val members = new ArrayBuffer[Member] 6 def join(name: String) = { 7 val m = new Member(name) 8 members += m 9 m 10 } 11 }
使用:
1 val chatter = new Network 2 val myFace = new Network 3 val fred = chatter.join("fred") 4 val wilma = chatter.join("wilma") 5 fred.contacts += wilma 6 val ngy = myFace.join("hongdao"); 7 fred.contacts += ngy; // error
解析:
val fred和wilma的类型为chatter.Member;ngy的类型为myFace.Memeber;fred.contacts的实际类型为ArrayBuffer[chatter.Member];
所以fred.contacts可以添加wilma,不可以添加ngy。
如果不希望这个效果,可以使用两种方式:
方式一:伴生对象
1 class Network { 2 private val members = new ArrayBuffer[Network.Member] 3 def join(name: String) = { 4 val m = new Network.Member(name) 5 members += m 6 m 7 } 8 } 9 object Network { 10 class Member(val name: String) { 11 val contacts = new ArrayBuffer[Member] 12 } 13 }
方式二:类型投影 Network#Member
任何Network的Member
1 import scala.collection.mutable.ArrayBuffer 2 3 class Network { 4 class Member(val name: String) { 5 val contacts = new ArrayBuffer[Network#Member] 6 } 7 private val members = new ArrayBuffer[Network#Member] 8 def join(name: String) = { 9 val m = new Member(name) 10 members += m 11 m 12 } 13 }
内部类访问外部实例:
外部类.this
外部类实例别名
1 class Network(val name: String) { outter => //外部类实例别名 2 class Member(val name: String) { 3 val contacts = new ArrayBuffer[Network#Member] 4 def out = println(Network.this.name) 5 def out2 = println(outter.name) 6 } 7 }