/**
* 第7章 类
*/
import scala.beans.BeanProperty
import scala.collection.mutable.ArrayBuffer
//########################### 7.1 简单类和无参方法 #################################
/**
* 在scala中,类并不声明为Public,一个Scala源文件可以包含多各类.
* 所有这些类都具有公共可见性.调用无参方法时,可以加(),也可以不加;
* 如果方法定义中不带括号,那么调用时就不能带括号
*/
class Counter {
private var value = 0
def increment() {
value += 1
}
def current() = value
def current2 = value
}
val counter = new Counter
counter.increment()
counter.current()
counter.current //无参时,定义有(),调用不加()也可以
counter.current2
//如果方法定义中不带括号,那么调用时就不能带括号
//counter.current2() 无参时,定义无()调用时就不能带括号,否则编译报错
//########################### 7.2 Getter、Setter方法 #################################
/**
* 非私有字段,那么getter方法民为age,setter方法名为age_=
* 如果字段是val,则只有getter方法被生成
*/
class Person {
var age = 0
val name = "Bob"
}
val fred = new Person
fred.age = 21
fred.age
fred.age_=(25)
fred.age
//fred.name_=("fred")报错
//也可以重新定义getter,setter方法
class Person2 {
private var priAge = 0
def age = priAge
def age_(newValue: Int) {
priAge = newValue
}
}
val tom = new Person2
tom.age_(22)
tom.age
//########################### 7.3 对象私有字段 #################################
/**
* 加了private或者private[this],编译生成的.class对象不会自动生成set/get方法
* 可以手写提供
*/
class Counter2 {
private var value = 0
private[this] var value2 = 0
}
//########################### 7.4 Bean属性 #################################
/**
* 为了与java互操作,将scala字段前加@BeanProperty时,会生成setXXX()和getXXX()方法
*/
class Person3 {
@BeanProperty var name: String = _
}
val per3 = new Person3
per3.getName
per3.setName("Lily")
per3.getName
//########################### 7.5 构造器 #################################
/**
* Scala的类构造器分为主构造器和辅助构造器
* ----------------------------------------------------------------------------------------
* ......主构造器参数 生成的字段/方法
* name: String 对象私有字段,如果没有方法使用那么,则没有该字段
* private val/var name: String 私有字段,私有的getter/setter方法
* val/var name: String 私有字段,公有的getter/setter方法
* @BeanProperty val/var: String 私有字段,公有的Scala版和JavaBean版的getter/setter方法
* ----------------------------------------------------------------------------------------
*/
//1)主构造器的参数直接放置在类名之后
class Person4(val name: String, private var age: Int) {
def description = name + " is " + age + " years old"
def birthday() {
age += 1
}
}
val per4 = new Person4("zuo", 22)
//per4.age
per4.name
per4.description
per4.birthday()
per4.description
//2)主构造器会执行类定义中的所有语句,方法不会执行,可以写在单独文件中debug跟踪看
class Person5(val name: String = "", val age: Int = 0) {
val aaa = 0;
println(aaa + 1)
println("Just construced anohter person")
def description = name + " is " + age + " years old"
println("Just construced anohter person")
}
val per5 = new Person5("zuo", 22)
//3)通过private设置主构造器的私有属性,就像java中单例模式一样,将构造方法私有,只有自己可以调用构造new新对象
class Person7 private(val name: String, private var age: Int) {
def description = name + " is " + age + " years old"
def birthday() {
age += 1
}
}
//val per7 = new Person7("zuo", 22) //No,编译不报错,但是运行会报错
//4)如果不带val或var的参数至少被一个方法所使用,它将被升格为字段;否则,该参数将不被保存为字段,仅仅是一个可以被主构造器中的代码访问的普通参数。
//未实现
class Person8(name: String, private var age: Int) {
def description = name + " is " + age + " years old"
def birthday() {
age += 1
}
}
val per8 = new Person8("Fred", 33)
//5)辅助构造器名称为this,通过不同参数进行区分,每一个辅助构造器都必须以主构造器或者已经定义的辅助构造器的调用开始
class Person9 {
private var name = ""
private var age = 0
def this(name: String) {
//辅助构造器
this() //先调主构造器
this.name = name
}
def this(name: String, age: Int) {
this(name) //先调用另一个辅助构造器
this.age = age
}
def this(age: Int, name: String) {
this(name) //先调用另一个辅助构造器
this.age = age
}
def description = name + " is " + age + " years old"
}
//通过不同参数进行区分
val per9 = new Person9("zuo")
val per92 = new Person9("zuo", 22)
val per93 = new Person9(22, "shuai")
//########################### 7.6 嵌套类 #################################
/**
* Scala中每一个示例都有一个内部类,内部类从属于实例
* Java中的内部类从属于外部类
*/
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)
members += m
m
}
}
val chatter = new Network
val myFace = new Network
val bob = chatter.join("Bob")
val wilma = chatter.join("Wilma")
bob.contacts += wilma //Ok
val barney = myFace.join("Barney")
//bob.contacts += barney //No
//创建新的内部对象
val liLy = new chatter.Member("Lily")
val liLy2 = new chatter.Member("Lily")
liLy == liLy2
/**
* 在Scala中,每个实例都有它自己的Member类,就和他们自己的members字段一样,也就是说,chatter.Member 和 myFace.Member是不同的2各类
* 如果想让members接受所有实例的Member,一般有2个办法:
*/
//1.将Member作为Network的半生对象存在:
class Network2 {
private val members = new ArrayBuffer[Network2.Member2]
def join(name: String) = {
val m = new Network2.Member2(name)
members += m
m
}
def description = "a network with members " + (for (m <- members) yield m.description).mkString(", ")
}
object Network2 {
class Member2(val name: String) {
val contacts = new ArrayBuffer[Member2]
def description = name + " with contacts " + (for (c <- contacts) yield c.name).mkString(" ")
}
}
val chatter2 = new Network2
val myFace2 = new Network2
val bob2 = chatter2.join("Bob")
val wilma2 = chatter2.join("Wilma")
bob2.contacts += wilma2 //Ok
val barney2 = myFace2.join("Barney")
bob2.contacts += barney2 //Ok
//2.使用类型投影, Network#Member : 任何Network的Member
class Network3 {
class Member3(val name: String) {
val contacts = new ArrayBuffer[Network3#Member3]
}
private val members = new ArrayBuffer[Member3]
def join(name: String) = {
val m = new Member3(name)
members += m
m
}
}
val chatter3 = new Network3
val myFace3 = new Network3
val bob3 = chatter3.join("Bob")
val wilma3 = chatter3.join("Wilma")
bob3.contacts += wilma3 //Ok
val barney3 = myFace3.join("Barney")
bob3.contacts += barney3 //Ok